145 lines
4.7 KiB
Text
145 lines
4.7 KiB
Text
|
# This runs in a new shell
|
||
|
readonly ACTION=${1}
|
||
|
readonly MODULE=${2}
|
||
|
readonly DIR=${3}
|
||
|
readonly URL=${4}
|
||
|
readonly REV=${6}
|
||
|
readonly -i PRINTLEVEL=${7}
|
||
|
readonly CLEAR_LINE=<%= clear_line %>
|
||
|
readonly PREFIX=.zim_degit
|
||
|
readonly TARBALL_TARGET=${DIR}/${PREFIX}_tarball.tar.gz
|
||
|
readonly INFO_TARGET=${DIR}/${PREFIX}_info
|
||
|
|
||
|
print_error() {
|
||
|
print -u2 -PR ${CLEAR_LINE}"%F{red}<%= error %>%B${MODULE}:%b ${1}%f"${2:+$'\n'${(F):- ${(f)^2}}}
|
||
|
}
|
||
|
|
||
|
print_done() {
|
||
|
if (( PRINTLEVEL > 0 )); then
|
||
|
if [[ -e ${DIR}/.gitmodules ]]; then
|
||
|
print -u2 -PR "%F{yellow}<%= warn %>%B${MODULE}:%b ${(C)1}. Module contains git submodules, which are not supported by Zim's degit and were not ${1}."
|
||
|
else
|
||
|
print -PR ${CLEAR_LINE}"<%= okay %>%B${MODULE}:%b ${(C)1}"
|
||
|
fi
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
download_tarball() {
|
||
|
setopt LOCAL_OPTIONS EXTENDED_GLOB
|
||
|
if [[ ${URL} =~ <%= url_regex %> ]]; then
|
||
|
local -r host=${match[3]}
|
||
|
local -r repo=${match[4]%.git}
|
||
|
fi
|
||
|
if [[ ${host} != github.com || -z ${repo} ]]; then
|
||
|
print_error "${URL} is not a valid github.com URL. Will not try to ${ACTION}."
|
||
|
return 1
|
||
|
fi
|
||
|
local -r headers_target=${DIR}/${PREFIX}_headers
|
||
|
{
|
||
|
local -i http_code
|
||
|
local -r tarball_url=https://api.github.com/repos/${repo}/tarball/${REV}
|
||
|
local header etag_in etag_out
|
||
|
if [[ -r ${INFO_TARGET} ]]; then
|
||
|
local -r info=(${(f)"$(<${INFO_TARGET})"})
|
||
|
if [[ ${URL} != ${info[1]} ]]; then
|
||
|
print_error "URL does not match. Expected ${URL}. Will not try to ${ACTION}."
|
||
|
return 1
|
||
|
fi
|
||
|
etag_out=${info[2]}
|
||
|
fi
|
||
|
if (( ${+commands[curl]} )); then
|
||
|
if ! ERR=$(command curl -fsSL ${etag_out:+-H} ${etag_out} -o ${TARBALL_TARGET} -D ${headers_target} ${tarball_url} 2>&1); then
|
||
|
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
|
||
|
command wget -q ${etag_out:+--header=${etag_out}} -O ${TARBALL_TARGET} -S ${tarball_url} 2>${headers_target}
|
||
|
fi
|
||
|
while IFS= read -r header; do
|
||
|
header=${${header## ##}%%$'\r'##}
|
||
|
if [[ ${header} == HTTP/* ]]; then
|
||
|
http_code=${${(s: :)header}[2]}
|
||
|
elif [[ ${${(L)header%%:*}%% ##} == 'etag' ]]; then
|
||
|
etag_in=${${header#*:}## ##}
|
||
|
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
|
||
|
if [[ -z ${etag_in} ]]; then
|
||
|
print_error "Error downloading ${tarball_url}, no ETag header found in response"
|
||
|
return 1
|
||
|
fi
|
||
|
if ! print -R ${URL}$'\n'"If-None-Match: ${etag_in}" >! ${INFO_TARGET} 2>/dev/null; then
|
||
|
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
|
||
|
}
|
||
|
|
||
|
() {
|
||
|
case ${ACTION} in
|
||
|
install)
|
||
|
{
|
||
|
create_dir ${DIR} && download_tarball && untar_tarball ${DIR} && print_done installed
|
||
|
} always {
|
||
|
# return 1 command does not change ${TRY_BLOCK_ERROR}, but only ${?}
|
||
|
(( TRY_BLOCK_ERROR = ? ))
|
||
|
command rm -f ${TARBALL_TARGET} 2>/dev/null
|
||
|
if (( TRY_BLOCK_ERROR )); then
|
||
|
command rm -rf ${DIR} 2>/dev/null
|
||
|
fi
|
||
|
}
|
||
|
;;
|
||
|
update)
|
||
|
if [[ ! -r ${INFO_TARGET} ]]; then
|
||
|
print_error "Module was not installed using Zim's degit. Will not try to update. You can disable this with the zmodule option -z|--frozen."
|
||
|
return 1
|
||
|
fi
|
||
|
local -r dir_new=${DIR}${PREFIX}_${RANDOM}
|
||
|
{
|
||
|
download_tarball || return 1
|
||
|
if [[ ! -e ${TARBALL_TARGET} ]]; then
|
||
|
if (( PRINTLEVEL > 0 )) print -PR ${CLEAR_LINE}"<%= okay %>%B${MODULE}:%b Already up to date"
|
||
|
return 0
|
||
|
fi
|
||
|
create_dir ${dir_new} && untar_tarball ${dir_new} || return 1
|
||
|
if ! ERR=$({ command mv -f ${INFO_TARGET} ${dir_new} && command mv -f ${dir_new} ${DIR} } 2>&1); then
|
||
|
print_error "Error updating ${DIR}" ${ERR}
|
||
|
return 1
|
||
|
fi
|
||
|
print_done updated
|
||
|
} always {
|
||
|
(( TRY_BLOCK_ERROR = ? ))
|
||
|
if (( TRY_BLOCK_ERROR )); then
|
||
|
command rm -f ${TARBALL_TARGET} 2>/dev/null
|
||
|
if [[ -f ${dir_new}/${INFO_TARGET:t} ]] command mv -f ${dir_new}/${INFO_TARGET:t} ${DIR}
|
||
|
command rm -rf ${dir_new} 2>/dev/null
|
||
|
fi
|
||
|
}
|
||
|
;;
|
||
|
esac
|
||
|
}
|