2021-04-03 10:35:28 -04:00
# This runs in a new shell
2022-01-10 20:41:50 -05:00
builtin emulate -L zsh -o EXTENDED_GLOB
2022-01-25 09:32:50 -05:00
readonly -i PRINTLEVEL=${1} SUBMODULES=${8}
2022-05-07 17:31:08 -04:00
readonly ACTION=${2} MODULE=${3} DIR=${4} URL=${5} REV=${7} ONPULL=${9} TEMP=.zdegit_${RANDOM}
2021-08-09 23:28:13 -04:00
readonly TARBALL_TARGET=${DIR}/${TEMP}_tarball.tar.gz INFO_TARGET=${DIR}/.zdegit
2021-04-03 10:35:28 -04:00
print_error() {
2021-11-08 11:38:56 -05:00
print -u2 -PlR <%= clear_line %>"%F{red}<%= error %>%B${MODULE}:%b ${1}%f" ${2:+${(F):- ${(f)^2}}}
2021-04-03 10:35:28 -04:00
}
2021-08-09 21:32:32 -04:00
print_okay() {
2021-09-21 17:36:32 -04:00
if (( PRINTLEVEL > 0 )); then
2021-09-23 15:29:40 -04:00
local -r log=${2:+${(F):- ${(f)^2}}}
2022-01-25 09:32:50 -05:00
if [[ ${SUBMODULES} -ne 0 && -e ${DIR}/.gitmodules ]]; then
2022-05-07 17:31:08 -04:00
print -u2 -PlR <%= clear_line %>"%F{yellow}<%= warn %>%B${MODULE}:%b ${1}. Module contains git submodules, which are not supported by Zim's degit. Use zmodule option %B--no-submodules%b to disable this warning.%f" ${log}
2021-04-03 10:35:28 -04:00
else
2022-05-07 17:31:08 -04:00
print -PlR <%= clear_line %>"<%= okay %>%B${MODULE}:%b ${1}" ${log}
2021-04-03 10:35:28 -04:00
fi
fi
}
2022-05-07 17:31:08 -04:00
handle() {
if [[ -n ${ONPULL} ]]; then
2022-05-09 19:36:03 -04:00
if ! ERR=$(builtin cd -q ${DIR} 2>&1 && builtin eval ${ONPULL} 2>&1); then
2022-05-07 17:31:08 -04:00
print_error 'Error during on-pull' ${ERR}
return 1
elif [[ ${PRINTLEVEL} -gt 1 && -n ${ERR} ]]; then
2022-05-09 19:36:03 -04:00
builtin set ${1} ${2:+${2}$'\n'}"On-pull output:"$'\n'${ERR}
2022-05-07 17:31:08 -04:00
fi
fi
print_okay "${@}"
}
2021-04-03 10:35:28 -04:00
download_tarball() {
2021-04-08 17:26:33 -04:00
local host repo
2021-04-03 10:35:28 -04:00
if [[ ${URL} =~ <%= url_regex %> ]]; then
2021-04-08 17:26:33 -04:00
host=${match[3]}
repo=${match[4]%.git}
2021-04-03 10:35:28 -04:00
fi
if [[ ${host} != github.com || -z ${repo} ]]; then
2021-08-10 10:56:25 -04:00
print_error "${URL} is not a valid GitHub URL. Will not try to ${ACTION}."
2021-04-03 10:35:28 -04:00
return 1
fi
2021-04-21 20:37:47 -04:00
local -r headers_target=${DIR}/${TEMP}_headers
2021-04-03 10:35:28 -04:00
{
2021-07-11 16:58:15 -04:00
local info_header header etag
2021-04-03 10:35:28 -04:00
if [[ -r ${INFO_TARGET} ]]; then
2021-04-08 17:26:33 -04:00
local -r info=("${(@f)"$(<${INFO_TARGET})"}")
2021-04-03 10:35:28 -04:00
if [[ ${URL} != ${info[1]} ]]; then
print_error "URL does not match. Expected ${URL}. Will not try to ${ACTION}."
return 1
fi
2021-04-08 17:26:33 -04:00
# Previous REV is in line 2, reserved for future use.
info_header=${info[3]}
2021-04-03 10:35:28 -04:00
fi
2021-04-08 17:26:33 -04:00
local -r tarball_url=https://api.github.com/repos/${repo}/tarball/${REV}
2021-04-03 10:35:28 -04:00
if (( ${+commands[curl]} )); then
2021-04-08 17:26:33 -04:00
if ! ERR=$(command curl -fsSL ${info_header:+-H} ${info_header} -o ${TARBALL_TARGET} -D ${headers_target} ${tarball_url} 2>&1); then
2021-04-03 10:35:28 -04:00
print_error "Error downloading ${tarball_url} with curl" ${ERR}
return 1
fi
else
# wget returns 8 when 304 Not Modified, so we cannot use wget's error codes
2021-04-08 17:26:33 -04:00
command wget -q ${info_header:+--header=${info_header}} -O ${TARBALL_TARGET} -S ${tarball_url} 2>${headers_target}
2021-04-03 10:35:28 -04:00
fi
2021-04-08 17:26:33 -04:00
local -i http_code
2021-04-03 10:35:28 -04:00
while IFS= read -r header; do
header=${${header## ##}%%$'\r'##}
if [[ ${header} == HTTP/* ]]; then
http_code=${${(s: :)header}[2]}
2021-09-23 15:29:40 -04:00
elif [[ ${${(L)header%%:*}%% ##} == etag ]]; then
2021-04-08 17:26:33 -04:00
etag=${${header#*:}## ##}
2021-04-03 10:35:28 -04:00
fi
done < ${headers_target}
if (( http_code == 304 )); then
# Not Modified
command rm -f ${TARBALL_TARGET} 2>/dev/null
return 0
elif (( http_code != 200 )); then
print_error "Error downloading ${tarball_url}, HTTP code ${http_code}"
return 1
fi
2021-04-08 17:26:33 -04:00
if [[ -z ${etag} ]]; then
2021-04-03 10:35:28 -04:00
print_error "Error downloading ${tarball_url}, no ETag header found in response"
return 1
fi
2021-11-08 11:38:56 -05:00
if ! print -lR "${URL}" "${REV}" "If-None-Match: ${etag}" >! ${INFO_TARGET} 2>/dev/null; then
2021-04-03 10:35:28 -04:00
print_error "Error creating or updating ${INFO_TARGET}"
return 1
fi
} always {
command rm -f ${headers_target} 2>/dev/null
}
}
untar_tarball() {
if ! ERR=$(command tar -C ${1} --strip=1 -xzf ${TARBALL_TARGET} 2>&1); then
print_error "Error extracting ${TARBALL_TARGET}" ${ERR}
return 1
fi
}
create_dir() {
if ! ERR=$(command mkdir -p ${1} 2>&1); then
print_error "Error creating ${1}" ${ERR}
return 1
fi
}
2021-09-23 15:29:40 -04:00
case ${ACTION} in
install)
{
2022-05-07 17:31:08 -04:00
create_dir ${DIR} && download_tarball && untar_tarball ${DIR} && handle Installed
2021-09-23 15:29:40 -04:00
} always {
# return 1 does not change ${TRY_BLOCK_ERROR}, only changes ${?}
(( TRY_BLOCK_ERROR = ? ))
command rm -f ${TARBALL_TARGET} 2>/dev/null
2022-01-25 09:32:50 -05:00
if (( TRY_BLOCK_ERROR )) command rm -rf ${DIR} 2>/dev/null
2021-09-23 15:29:40 -04:00
}
;;
update)
if [[ ! -r ${INFO_TARGET} ]]; then
2021-10-19 09:36:51 -04:00
if (( PRINTLEVEL > 0 )); then
2021-11-15 19:37:40 -05:00
print -u2 -PR <%= clear_line %>"%F{yellow}<%= warn %>%B${MODULE}:%b Module was not installed using Zim's degit. Will not try to update. Use zmodule option %B-z%b|%B--frozen%b to disable this warning.%f"
2021-10-19 09:36:51 -04:00
fi
return 0
2021-09-23 15:29:40 -04:00
fi
readonly DIR_NEW=${DIR}${TEMP}
{
download_tarball || return 1
if [[ ! -e ${TARBALL_TARGET} ]]; then
2022-05-07 17:31:08 -04:00
handle 'Already up to date'
return ${?}
2021-09-23 15:29:40 -04:00
fi
create_dir ${DIR_NEW} && untar_tarball ${DIR_NEW} || return 1
if (( ${+commands[diff]} )); then
LOG=$(command diff -x '.zdegit*' -x '*.zwc' -x '*.zwc.old' -qr ${DIR} ${DIR_NEW} 2>/dev/null)
LOG=${${LOG//${DIR_NEW}/new}//${DIR}/old}
fi
if ! ERR=$({ command cp -f ${INFO_TARGET} ${DIR_NEW} && \
command rm -rf ${DIR} && command mv -f ${DIR_NEW} ${DIR} } 2>&1); then
print_error "Error updating ${DIR}" ${ERR}
2021-04-03 10:35:28 -04:00
return 1
fi
2022-05-07 17:31:08 -04:00
handle Updated ${LOG}
2021-09-23 15:29:40 -04:00
} always {
command rm -f ${TARBALL_TARGET} 2>/dev/null
command rm -rf ${DIR_NEW} 2>/dev/null
}
;;
esac