From ee93f7944fc49c779dfe7e2bb88b79d599783bef Mon Sep 17 00:00:00 2001 From: Eric Nielsen <4120606+ericbn@users.noreply.github.com> Date: Tue, 28 Mar 2023 07:56:37 -0500 Subject: [PATCH] Don't use a new shell to run tool anymore This was needed when we were using xargs, but we're already using zargs instead for quite some time. Pro is that now common functions are reused instead of repeated. Con (or change) is that due to that reuse, and in favor of simplification, the warning for a module with git submodules in degit is in a separate line from a separate print call now. Also fix regressions from recent commits: - Need to call _zimfw_source_zimrc twice with 1 and 2 flags instead of with flag 3, since flag 2 must be used after module is installed or updated. - Need to call _zimfw_print_okay from the function that handles on-pull, since we want to include the on-pull output in verbose mode. This function was called just `handle` before, now it's called _zimfw_pull_print_okay. Still need to figure out how to return a final error code from _zimfw_run_tool_action. --- src/stage2/29_zimfw_build_login_init.zsh.erb | 2 +- src/stage2/70_zimfw_print_error.zsh.erb | 3 + src/stage2/70_zimfw_print_okay.zsh.erb | 3 + src/stage2/70_zimfw_run_tool.zsh.erb | 44 -- src/stage2/70_zimfw_run_tool_action.zsh.erb | 7 - src/stage2/71_zimfw_pull_print_okay.zsh.erb | 13 + src/stage2/75_zimfw_tool_degit.zsh.erb | 152 ++++++ src/stage2/75_zimfw_tool_git.zsh.erb | 94 ++++ src/stage2/77_zimfw_run_tool.zsh.erb | 45 ++ src/stage2/78_zimfw_run_tool_action.zsh.erb | 5 + src/stage2/80_zimfw.zsh.erb | 10 +- src/templates/login_init.zsh.erb | 1 - src/tools/degit.zsh.erb | 173 ------ src/tools/git.zsh.erb | 116 ---- src/zimfw.zsh.erb | 10 - zimfw.zsh | 534 +++++++++---------- zimfw.zsh.gz | Bin 0 -> 10245 bytes 17 files changed, 577 insertions(+), 635 deletions(-) create mode 100644 src/stage2/70_zimfw_print_error.zsh.erb create mode 100644 src/stage2/70_zimfw_print_okay.zsh.erb delete mode 100644 src/stage2/70_zimfw_run_tool.zsh.erb delete mode 100644 src/stage2/70_zimfw_run_tool_action.zsh.erb create mode 100644 src/stage2/71_zimfw_pull_print_okay.zsh.erb create mode 100644 src/stage2/75_zimfw_tool_degit.zsh.erb create mode 100644 src/stage2/75_zimfw_tool_git.zsh.erb create mode 100644 src/stage2/77_zimfw_run_tool.zsh.erb create mode 100644 src/stage2/78_zimfw_run_tool_action.zsh.erb delete mode 100644 src/templates/login_init.zsh.erb delete mode 100644 src/tools/degit.zsh.erb delete mode 100644 src/tools/git.zsh.erb create mode 100644 zimfw.zsh.gz diff --git a/src/stage2/29_zimfw_build_login_init.zsh.erb b/src/stage2/29_zimfw_build_login_init.zsh.erb index 98dc03a..981e577 100644 --- a/src/stage2/29_zimfw_build_login_init.zsh.erb +++ b/src/stage2/29_zimfw_build_login_init.zsh.erb @@ -5,6 +5,6 @@ _zimfw_build_login_init() { command mv -f ${ztarget}{,.old} || return 1 fi _zimfw_mv =( - print -nR "<%= render_escaped("src/templates/login_init.zsh.erb") %>" + print '# Do nothing. This file is deprecated.' ) ${ztarget} } diff --git a/src/stage2/70_zimfw_print_error.zsh.erb b/src/stage2/70_zimfw_print_error.zsh.erb new file mode 100644 index 0000000..266c6cd --- /dev/null +++ b/src/stage2/70_zimfw_print_error.zsh.erb @@ -0,0 +1,3 @@ +_zimfw_print_error() { + print -u2 -PlR <%= clear_line %>"%F{red}<%= error %>%B${_zname}:%b ${1}%f" ${2:+${(F):- ${(f)^2}}} +} diff --git a/src/stage2/70_zimfw_print_okay.zsh.erb b/src/stage2/70_zimfw_print_okay.zsh.erb new file mode 100644 index 0000000..eca0ca7 --- /dev/null +++ b/src/stage2/70_zimfw_print_okay.zsh.erb @@ -0,0 +1,3 @@ +_zimfw_print_okay() { + if (( _zprintlevel > ${2:-0} )) print -PlR <%= clear_line %>"<%= okay %>%B${_zname}:%b ${1}" ${3:+${(F):- ${(f)^3}}} +} diff --git a/src/stage2/70_zimfw_run_tool.zsh.erb b/src/stage2/70_zimfw_run_tool.zsh.erb deleted file mode 100644 index 993584e..0000000 --- a/src/stage2/70_zimfw_run_tool.zsh.erb +++ /dev/null @@ -1,44 +0,0 @@ -_zimfw_run_tool() { - local -r zname=${1} - if [[ -z ${_zurls[${zname}]} ]]; then - if (( _zprintlevel > 1 )) print -PR <%= clear_line %>"<%= okay %>%B${zname}:%b Skipping external module" - return 0 - fi - if (( _zfrozens[${zname}] )); then - if (( _zprintlevel > 1 )) print -PR <%= clear_line %>"<%= okay %>%B${zname}:%b Skipping frozen module" - return 0 - fi - case ${_zargs_action} in - install) - if [[ -e ${_zdirs[${zname}]} ]]; then - if (( _zprintlevel > 1 )) print -PR <%= clear_line %>"<%= okay %>%B${zname}:%b Skipping already installed module" - return 0 - fi - _zimfw_print -nR <%= clear_line %>"Installing ${zname}<%= ellipsis %>" - ;; - check|update) - if [[ ! -d ${_zdirs[${zname}]} ]]; then - print -u2 -PR <%= clear_line %>"%F{red}<%= error %>%B${zname}:%b Not installed. Run %Bzimfw install%b to install.%f" - return 1 - fi - if [[ ${_zargs_action} == check ]]; then - if (( _zprintlevel > 1 )) print -nR <%= clear_line %>"Checking ${zname}<%= ellipsis %>" - else - _zimfw_print -nR <%= clear_line %>"Updating ${zname}<%= ellipsis %>" - fi - ;; - *) - print -u2 -PR <%= clear_line %>"%F{red}<%= error %>%B${zname}:%b Unknown action ${_zargs_action}%f" - return 1 - ;; - esac - local zcmd - case ${_ztools[${zname}]} in -<%= render_tools("src/tools/*", "zcmd") %> - *) - print -u2 -PR "<%= clear_line %>%F{red}<%= error %>%B${zname}:%b Unknown tool ${_ztools[${zname}]}%f" - return 1 - ;; - esac - zsh -c ${zcmd} ${_ztools[${zname}]} "${_zprintlevel}" "${_zargs_action}" "${zname}" "${_zdirs[${zname}]}" "${_zurls[${zname}]}" "${_ztypes[${zname}]}" "${_zrevs[${zname}]}" "${_zsubmodules[${zname}]}" "${_zonpulls[${zname}]}" -} diff --git a/src/stage2/70_zimfw_run_tool_action.zsh.erb b/src/stage2/70_zimfw_run_tool_action.zsh.erb deleted file mode 100644 index eab8db9..0000000 --- a/src/stage2/70_zimfw_run_tool_action.zsh.erb +++ /dev/null @@ -1,7 +0,0 @@ -_zimfw_run_tool_action() { - local -r _zargs_action=${1} - zargs -n 1 -P 0 -- "${_znames[@]}" -- _zimfw_run_tool - # Ignore return from zargs with -P. Was missing values before zsh 5.9, and - # it's intermittently failing in zsh 5.9 and macOS. See https://www.zsh.org/mla/workers/2022/msg00611.html - return 0 -} diff --git a/src/stage2/71_zimfw_pull_print_okay.zsh.erb b/src/stage2/71_zimfw_pull_print_okay.zsh.erb new file mode 100644 index 0000000..2be6c63 --- /dev/null +++ b/src/stage2/71_zimfw_pull_print_okay.zsh.erb @@ -0,0 +1,13 @@ +_zimfw_pull_print_okay() { + if [[ -n ${zonpull} ]]; then + local zerr + if ! zerr=$(builtin cd -q ${zdir} 2>&1 && builtin eval ${zonpull} 2>&1); then + _zimfw_print_error 'Error during on-pull' ${zerr} + return 1 + elif [[ ${_zprintlevel} -gt 1 && -n ${zerr} ]]; then + # Overrides ${3} to include the on-pull output, to be used by _zimfw_print_okay below. + builtin set ${1} ${2:-0} ${3:+${3}$'\n'}'On-pull output:'$'\n'${zerr} + fi + fi + _zimfw_print_okay "${@}" +} diff --git a/src/stage2/75_zimfw_tool_degit.zsh.erb b/src/stage2/75_zimfw_tool_degit.zsh.erb new file mode 100644 index 0000000..eb00706 --- /dev/null +++ b/src/stage2/75_zimfw_tool_degit.zsh.erb @@ -0,0 +1,152 @@ +_zimfw_download_tarball() { + local host repo + if [[ ${zurl} =~ <%= url_regex %> ]]; then + host=${match[3]} + repo=${match[4]%.git} + fi + if [[ ${host} != github.com || -z ${repo} ]]; then + _zimfw_print_error "${zurl} is not a valid GitHub zurl. Will not try to ${_zaction}." + return 1 + fi + local -r headers_target=${zdir}/${ztemp}_headers + { + local info_header header etag zerr + if [[ -r ${zinfo_target} ]]; then + local -r info=("${(@f)"$(<${zinfo_target})"}") + if [[ ${zurl} != ${info[1]} ]]; then + _zimfw_print_error "zurl does not match. Expected ${zurl}. Will not try to ${_zaction}." + return 1 + fi + # Previous zrev is in line 2, reserved for future use. + info_header=${info[3]} + fi + local -r tarball_url=https://api.github.com/repos/${repo}/tarball/${zrev} + if [[ ${_zaction} == check ]]; then + if [[ -z ${info_header} ]] return 0 + if (( ${+commands[curl]} )); then + command curl -IfsL -H ${info_header} ${tarball_url} >${headers_target} + else + command wget --spider -qS --header=${info_header} ${tarball_url} 2>${headers_target} + fi + else + if (( ${+commands[curl]} )); then + if ! zerr=$(command curl -fsSL ${info_header:+-H} ${info_header} -o ${ztarball_target} -D ${headers_target} ${tarball_url} 2>&1); then + _zimfw_print_error "Error downloading ${tarball_url} with curl" ${zerr} + return 1 + fi + else + # wget returns 8 when 304 Not Modified, so we cannot use wget's error codes + command wget -qS ${info_header:+--header=${info_header}} -O ${ztarball_target} ${tarball_url} 2>${headers_target} + fi + fi + local -i http_code + while IFS= read -r header; do + header=${${header## ##}%%$'\r'##} + if [[ ${header} == HTTP/* ]]; then + http_code=${${(s: :)header}[2]} + elif [[ ${${(L)header%%:*}%% ##} == etag ]]; then + etag=${${header#*:}## ##} + fi + done < ${headers_target} + if (( http_code == 304 )); then + # Not Modified + command rm -f ${ztarball_target} 2>/dev/null + return 0 + elif (( http_code != 200 )); then + _zimfw_print_error "Error downloading ${tarball_url}, HTTP code ${http_code}" + return 1 + fi + if [[ -z ${etag} ]]; then + _zimfw_print_error "Error downloading ${tarball_url}, no ETag header found in response" + return 1 + fi + if [[ ${_zaction} == check ]]; then + command touch ${ztarball_target} # Update available + else + if ! print -lR "${zurl}" "${zrev}" "If-None-Match: ${etag}" >! ${zinfo_target} 2>/dev/null; then + _zimfw_print_error "Error creating or updating ${zinfo_target}" + return 1 + fi + fi + } always { + command rm -f ${headers_target} 2>/dev/null + } +} + +_zimfw_untar_tarball() { + local zerr + if ! zerr=$(command tar -C ${1} --strip=1 -xzf ${ztarball_target} 2>&1); then + _zimfw_print_error "Error extracting ${ztarball_target}" ${zerr} + return 1 + fi +} + +_zimfw_create_dir() { + local zerr + if ! zerr=$(command mkdir -p ${1} 2>&1); then + _zimfw_print_error "Error creating ${1}" ${zerr} + return 1 + fi +} + +_zimfw_tool_degit() { + local -ri zsubmodules=${5} + local -r zdir=${1} zurl=${2} zrev=${4} zonpull=${6} ztemp=.zdegit_${sysparams[pid]} + local -r ztarball_target=${zdir}/${ztemp}_tarball.tar.gz zinfo_target=${zdir}/.zdegit + case ${_zaction} in + install) + { + _zimfw_create_dir ${zdir} && _zimfw_download_tarball && _zimfw_untar_tarball ${zdir} && _zimfw_pull_print_okay Installed || return 1 + } always { + # return 1 does not change ${TRY_BLOCK_ERROR}, only changes ${?} + (( TRY_BLOCK_ERROR = ? )) + command rm -f ${ztarball_target} 2>/dev/null + if (( TRY_BLOCK_ERROR )) command rm -rf ${zdir} 2>/dev/null + } + ;; + check|update) + if [[ ! -r ${zinfo_target} ]]; then + if (( _zprintlevel > 0 )); then + print -u2 -PR <%= clear_line %>"%F{yellow}<%= warn %>%B${_zname}:%b Module was not installed using Zim's degit. Will not try to ${_zaction}. Use zmodule option %B-z%b|%B--frozen%b to disable this warning.%f" + fi + return 0 + fi + readonly zdir_new=${zdir}${ztemp} + { + local zerr zlog + _zimfw_download_tarball || return 1 + if [[ ${_zaction} == check ]]; then + if [[ -e ${ztarball_target} ]]; then + _zimfw_print_okay 'Update available' + return 4 + fi + _zimfw_print_okay 'Already up to date' 1 + return 0 + else + if [[ -e ${ztarball_target} ]]; then + _zimfw_create_dir ${zdir_new} && _zimfw_untar_tarball ${zdir_new} || return 1 + if (( ${+commands[diff]} )); then + zlog=$(command diff -x '.zdegit*' -x '*.zwc' -x '*.zwc.old' -qr ${zdir} ${zdir_new} 2>/dev/null) + zlog=${${zlog//${zdir_new}/new}//${zdir}/old} + fi + if ! zerr=$({ command cp -f ${zinfo_target} ${zdir_new} && \ + command rm -rf ${zdir} && command mv -f ${zdir_new} ${zdir} } 2>&1); then + _zimfw_print_error "Error updating ${zdir}" ${zerr} + return 1 + fi + _zimfw_pull_print_okay Updated 0 ${zlog} || return 1 + else + _zimfw_pull_print_okay 'Already up to date' || return 1 + fi + fi + } always { + command rm -f ${ztarball_target} 2>/dev/null + command rm -rf ${zdir_new} 2>/dev/null + } + ;; + esac + # Check after successful install or update + if [[ ${_zprintlevel} -gt 0 && ${zsubmodules} -ne 0 && -e ${zdir}/.gitmodules ]]; then + print -u2 -PR <%= clear_line %>"%F{yellow}<%= warn %>%B${_zname}:%b Module contains git submodules, which are not supported by Zim's degit. Use zmodule option %B--no-submodules%b to disable this warning.%f" + fi +} diff --git a/src/stage2/75_zimfw_tool_git.zsh.erb b/src/stage2/75_zimfw_tool_git.zsh.erb new file mode 100644 index 0000000..579287b --- /dev/null +++ b/src/stage2/75_zimfw_tool_git.zsh.erb @@ -0,0 +1,94 @@ +_zimfw_tool_git() { + local -ri zsubmodules=${5} + local -r zdir=${1} zurl=${2} ztype=${3} zonpull=${6} + local zrev=${4} ztorev zerr zout zlog + case ${_zaction} in + install) + if zerr=$(command git clone ${zrev:+-b} ${zrev} -q --config core.autocrlf=false ${${zsubmodules:#0}:+--recursive} -- ${zurl} ${zdir} 2>&1); then + _zimfw_pull_print_okay Installed + else + _zimfw_print_error 'Error during git clone' ${zerr} + return 1 + fi + ;; + check|update) + if [[ ! -r ${zdir}/.git ]]; then + if (( _zprintlevel > 0 )); then + print -u2 -PR <%= clear_line %>"%F{yellow}<%= warn %>%B${_zname}:%b Module was not installed using git. Will not try to ${_zaction}. Use zmodule option %B-z%b|%B--frozen%b to disable this warning.%f" + fi + return 0 + fi + if [[ ${zurl} != $(command git -C ${zdir} config --get remote.origin.url) ]]; then + _zimfw_print_error "zurl does not match. Expected ${zurl}. Will not try to ${_zaction}." + return 1 + fi + if ! zerr=$(command git -C ${zdir} fetch -pqt origin 2>&1); then + _zimfw_print_error 'Error during git fetch' ${zerr} + return 1 + fi + if [[ ${ztype} == branch ]]; then + if [[ -z ${zrev} ]]; then + # Get HEAD remote branch + if ! zerr=$(command git -C ${zdir} remote set-head origin -a 2>&1); then + _zimfw_print_error 'Error during git remote set-head' ${zerr} + return 1 + fi + if zrev=$(command git -C ${zdir} symbolic-ref --short refs/remotes/origin/HEAD 2>&1); then + zrev=${zrev#origin/} + else + _zimfw_print_error 'Error during git symbolic-ref' ${zrev} + return 1 + fi + fi + ztorev=${zrev}@{u} + if [[ ${_zaction} == check ]]; then + local -ri behind=$(command git -C ${zdir} rev-list --count ${zrev}..${ztorev} -- 2>/dev/null) + if (( behind )); then + _zimfw_print_okay "Update available [behind ${behind}]" + return 4 + else + _zimfw_print_okay 'Already up to date' 1 + return 0 + fi + fi + else + if [[ ${zrev} == $(command git -C ${zdir} describe --tags --exact-match 2>/dev/null) ]]; then + if [[ ${_zaction} == check ]]; then + _zimfw_print_okay 'Already up to date' 1 + return 0 + else + _zimfw_pull_print_okay 'Already up to date' + return ${?} + fi + fi + if [[ ${_zaction} == check ]]; then + _zimfw_print_okay 'Update available' + return 4 + fi + ztorev=${zrev} + fi + zlog=$(command git -C ${zdir} log --graph --color --format='%C(yellow)%h%C(reset) %s %C(cyan)(%cr)%C(reset)' ..${ztorev} -- 2>/dev/null) + if ! zerr=$(command git -C ${zdir} checkout -q ${zrev} -- 2>&1); then + _zimfw_print_error 'Error during git checkout' ${zerr} + return 1 + fi + if [[ ${ztype} == branch ]]; then + if ! zout=$(command git -C ${zdir} merge --ff-only --no-progress -n 2>&1); then + _zimfw_print_error 'Error during git merge' ${zout} + return 1 + fi + # keep just first line of zout + zout=${zout%%($'\n'|$'\r')*} + else + zout="Updating to ${ztype} ${zrev}" + fi + if (( zsubmodules )); then + if ! zerr=$(command git -C ${zdir} submodule update --init --recursive -q -- 2>&1); then + _zimfw_print_error 'Error during git submodule update' ${zerr} + return 1 + fi + fi + _zimfw_pull_print_okay ${zout} 0 ${zlog} + ;; + esac +} diff --git a/src/stage2/77_zimfw_run_tool.zsh.erb b/src/stage2/77_zimfw_run_tool.zsh.erb new file mode 100644 index 0000000..98b9232 --- /dev/null +++ b/src/stage2/77_zimfw_run_tool.zsh.erb @@ -0,0 +1,45 @@ +_zimfw_run_tool() { + local -r _zname=${1} + if [[ -z ${_zurls[${_zname}]} ]]; then + _zimfw_print_okay 'Skipping external module' 1 + return 0 + fi + if (( _zfrozens[${_zname}] )); then + _zimfw_print_okay 'Skipping frozen module' 1 + return 0 + fi + case ${_zaction} in + install) + if [[ -e ${_zdirs[${_zname}]} ]]; then + _zimfw_print_okay 'Skipping already installed module' 1 + return 0 + fi + _zimfw_print -nR <%= clear_line %>"Installing ${_zname}<%= ellipsis %>" + ;; + check|update) + if [[ ! -d ${_zdirs[${_zname}]} ]]; then + _zimfw_print_error 'Not installed. Run %Bzimfw install%b to install.' + return 1 + fi + if [[ ${_zaction} == check ]]; then + if (( _zprintlevel > 1 )) print -nR <%= clear_line %>"Checking ${_zname}<%= ellipsis %>" + else + _zimfw_print -nR <%= clear_line %>"Updating ${_zname}<%= ellipsis %>" + fi + ;; + *) + _zimfw_print_error "Unknown action ${_zaction}" + return 1 + ;; + esac + local -r ztool=${_ztools[${_zname}]} + case ${ztool} in + degit|git) + _zimfw_tool_${ztool} "${_zdirs[${_zname}]}" "${_zurls[${_zname}]}" "${_ztypes[${_zname}]}" "${_zrevs[${_zname}]}" "${_zsubmodules[${_zname}]}" "${_zonpulls[${_zname}]}" + ;; + *) + _zimfw_print_error "Unknown tool ${ztool}" + return 1 + ;; + esac +} diff --git a/src/stage2/78_zimfw_run_tool_action.zsh.erb b/src/stage2/78_zimfw_run_tool_action.zsh.erb new file mode 100644 index 0000000..f826788 --- /dev/null +++ b/src/stage2/78_zimfw_run_tool_action.zsh.erb @@ -0,0 +1,5 @@ +_zimfw_run_tool_action() { + local -r _zaction=${1} + _zimfw_source_zimrc 1 && zargs -n 1 -P 0 -- "${_znames[@]}" -- _zimfw_run_tool + return 0 +} diff --git a/src/stage2/80_zimfw.zsh.erb b/src/stage2/80_zimfw.zsh.erb index 7783923..c6410b2 100644 --- a/src/stage2/80_zimfw.zsh.erb +++ b/src/stage2/80_zimfw.zsh.erb @@ -72,22 +72,22 @@ Options: ;; check) _zrestartmsg= - _zimfw_source_zimrc 3 && _zimfw_run_tool_action ${1} || return 1 + _zimfw_run_tool_action ${1} || return 1 (( _zprintlevel-- )) _zimfw_print -PR "<%= done %>Done with ${1}." # Only printed in verbose mode ;; init) _zrestartmsg= - _zimfw_source_zimrc 3 && _zimfw_run_tool_action install || return 1 + _zimfw_run_tool_action install || return 1 (( _zprintlevel-- )) _zimfw_print -PR "<%= done %>Done with install." # Only printed in verbose mode - _zimfw_build && _zimfw_compile + _zimfw_source_zimrc 2 && _zimfw_build && _zimfw_compile ;; install|update) - _zimfw_source_zimrc 3 && _zimfw_run_tool_action ${1} || return 1 + _zimfw_run_tool_action ${1} || return 1 _zimfw_print -PR "<%= done %>Done with ${1}.${_zrestartmsg}" (( _zprintlevel-- )) - _zimfw_build && _zimfw_compile + _zimfw_source_zimrc 2 && _zimfw_build && _zimfw_compile ;; uninstall) _zimfw_source_zimrc 2 && _zimfw_list_unuseds && _zimfw_uninstall ;; check-version) _zimfw_check_version 1 ;; diff --git a/src/templates/login_init.zsh.erb b/src/templates/login_init.zsh.erb deleted file mode 100644 index 0cf3b1b..0000000 --- a/src/templates/login_init.zsh.erb +++ /dev/null @@ -1 +0,0 @@ -# Do nothing. This file is deprecated. diff --git a/src/tools/degit.zsh.erb b/src/tools/degit.zsh.erb deleted file mode 100644 index 89e048f..0000000 --- a/src/tools/degit.zsh.erb +++ /dev/null @@ -1,173 +0,0 @@ -# This runs in a new shell -builtin emulate -L zsh -o EXTENDED_GLOB -integer PRINTLEVEL=${1} -readonly -i SUBMODULES=${8} -readonly ACTION=${2} MODULE=${3} DIR=${4} URL=${5} REV=${7} ONPULL=${9} TEMP=.zdegit_${sysparams[pid]} -readonly TARBALL_TARGET=${DIR}/${TEMP}_tarball.tar.gz INFO_TARGET=${DIR}/.zdegit - -print_error() { - print -u2 -PlR <%= clear_line %>"%F{red}<%= error %>%B${MODULE}:%b ${1}%f" ${2:+${(F):- ${(f)^2}}} -} - -print_okay() { - if (( PRINTLEVEL > 0 )); then - local -r log=${2:+${(F):- ${(f)^2}}} - if [[ ${SUBMODULES} -ne 0 && -e ${DIR}/.gitmodules ]]; then - 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} - else - print -PlR <%= clear_line %>"<%= okay %>%B${MODULE}:%b ${1}" ${log} - fi - fi -} - -on_pull() { - if [[ -n ${ONPULL} ]]; then - if ! ERR=$(builtin cd -q ${DIR} 2>&1 && builtin eval ${ONPULL} 2>&1); then - print_error 'Error during on-pull' ${ERR} - return 1 - elif [[ ${PRINTLEVEL} -gt 1 && -n ${ERR} ]]; then - builtin set ${1} ${2:+${2}$'\n'}"On-pull output:"$'\n'${ERR} - fi - fi -} - -download_tarball() { - local host repo - if [[ ${URL} =~ <%= url_regex %> ]]; then - host=${match[3]} - repo=${match[4]%.git} - fi - if [[ ${host} != github.com || -z ${repo} ]]; then - print_error "${URL} is not a valid GitHub URL. Will not try to ${ACTION}." - return 1 - fi - local -r headers_target=${DIR}/${TEMP}_headers - { - local info_header header etag - 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 - # Previous REV is in line 2, reserved for future use. - info_header=${info[3]} - fi - local -r tarball_url=https://api.github.com/repos/${repo}/tarball/${REV} - if [[ ${ACTION} == check ]]; then - if [[ -z ${info_header} ]] return 0 - if (( ${+commands[curl]} )); then - command curl -IfsL -H ${info_header} ${tarball_url} >${headers_target} - else - command wget --spider -qS --header=${info_header} ${tarball_url} 2>${headers_target} - fi - else - if (( ${+commands[curl]} )); then - if ! ERR=$(command curl -fsSL ${info_header:+-H} ${info_header} -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 -qS ${info_header:+--header=${info_header}} -O ${TARBALL_TARGET} ${tarball_url} 2>${headers_target} - fi - fi - local -i http_code - while IFS= read -r header; do - header=${${header## ##}%%$'\r'##} - if [[ ${header} == HTTP/* ]]; then - http_code=${${(s: :)header}[2]} - elif [[ ${${(L)header%%:*}%% ##} == etag ]]; then - etag=${${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} ]]; then - print_error "Error downloading ${tarball_url}, no ETag header found in response" - return 1 - fi - if [[ ${ACTION} == check ]]; then - command touch ${TARBALL_TARGET} # Update available - else - if ! print -lR "${URL}" "${REV}" "If-None-Match: ${etag}" >! ${INFO_TARGET} 2>/dev/null; then - print_error "Error creating or updating ${INFO_TARGET}" - return 1 - fi - 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} && on_pull && print_okay Installed - } always { - # return 1 does not change ${TRY_BLOCK_ERROR}, only changes ${?} - (( TRY_BLOCK_ERROR = ? )) - command rm -f ${TARBALL_TARGET} 2>/dev/null - if (( TRY_BLOCK_ERROR )) command rm -rf ${DIR} 2>/dev/null - } - ;; - check|update) - if [[ ! -r ${INFO_TARGET} ]]; then - if (( PRINTLEVEL > 0 )); then - print -u2 -PR <%= clear_line %>"%F{yellow}<%= warn %>%B${MODULE}:%b Module was not installed using Zim's degit. Will not try to ${ACTION}. Use zmodule option %B-z%b|%B--frozen%b to disable this warning.%f" - fi - return 0 - fi - readonly DIR_NEW=${DIR}${TEMP} - { - download_tarball || return 1 - if [[ ${ACTION} == check ]]; then - if [[ -e ${TARBALL_TARGET} ]]; then - print_okay 'Update available' - else - (( PRINTLEVEL-- )) - print_okay 'Already up to date' - fi - else - if [[ ! -e ${TARBALL_TARGET} ]]; then - on_pull && print_okay 'Already up to date' - return ${?} - 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} - return 1 - fi - on_pull && print_okay Updated ${LOG} - fi - } always { - command rm -f ${TARBALL_TARGET} 2>/dev/null - command rm -rf ${DIR_NEW} 2>/dev/null - } - ;; -esac diff --git a/src/tools/git.zsh.erb b/src/tools/git.zsh.erb deleted file mode 100644 index c11e46c..0000000 --- a/src/tools/git.zsh.erb +++ /dev/null @@ -1,116 +0,0 @@ -# This runs in a new shell -builtin emulate -L zsh -integer PRINTLEVEL=${1} -readonly -i SUBMODULES=${8} -readonly ACTION=${2} MODULE=${3} DIR=${4} URL=${5} TYPE=${6} ONPULL=${9} -REV=${7} - -print_error() { - print -u2 -PlR <%= clear_line %>"%F{red}<%= error %>%B${MODULE}:%b ${1}%f" ${2:+${(F):- ${(f)^2}}} -} - -print_okay() { - if (( PRINTLEVEL > 0 )) print -PlR <%= clear_line %>"<%= okay %>%B${MODULE}:%b ${1}" ${2:+${(F):- ${(f)^2}}} -} - -on_pull() { - if [[ -n ${ONPULL} ]]; then - if ! ERR=$(builtin cd -q ${DIR} 2>&1 && builtin eval ${ONPULL} 2>&1); then - print_error 'Error during on-pull' ${ERR} - return 1 - elif [[ ${PRINTLEVEL} -gt 1 && -n ${ERR} ]]; then - builtin set ${1} ${2:+${2}$'\n'}'On-pull output:'$'\n'${ERR} - fi - fi -} - -case ${ACTION} in - install) - if ERR=$(command git clone ${REV:+-b} ${REV} -q --config core.autocrlf=false ${${SUBMODULES:#0}:+--recursive} -- ${URL} ${DIR} 2>&1); then - on_pull && print_okay Installed - else - print_error 'Error during git clone' ${ERR} - return 1 - fi - ;; - check|update) - if [[ ! -r ${DIR}/.git ]]; then - if (( PRINTLEVEL > 0 )); then - print -u2 -PR <%= clear_line %>"%F{yellow}<%= warn %>%B${MODULE}:%b Module was not installed using git. Will not try to ${ACTION}. Use zmodule option %B-z%b|%B--frozen%b to disable this warning.%f" - fi - return 0 - fi - if [[ ${URL} != $(command git -C ${DIR} config --get remote.origin.url) ]]; then - print_error "URL does not match. Expected ${URL}. Will not try to ${ACTION}." - return 1 - fi - if ! ERR=$(command git -C ${DIR} fetch -pqt origin 2>&1); then - print_error 'Error during git fetch' ${ERR} - return 1 - fi - if [[ ${TYPE} == branch ]]; then - if [[ -z ${REV} ]]; then - # Get HEAD remote branch - if ! ERR=$(command git -C ${DIR} remote set-head origin -a 2>&1); then - print_error 'Error during git remote set-head' ${ERR} - return 1 - fi - if REV=$(command git -C ${DIR} symbolic-ref --short refs/remotes/origin/HEAD 2>&1); then - REV=${REV#origin/} - else - print_error 'Error during git symbolic-ref' ${REV} - return 1 - fi - fi - TO_REV=${REV}@{u} - if [[ ${ACTION} == check ]]; then - local -ri behind=$(command git -C ${DIR} rev-list --count ${REV}..${TO_REV} -- 2>/dev/null) - if (( behind )); then - print_okay "Update available [behind ${behind}]" - else - (( PRINTLEVEL-- )) - print_okay 'Already up to date' - fi - return 0 - fi - else - if [[ ${REV} == $(command git -C ${DIR} describe --tags --exact-match 2>/dev/null) ]]; then - if [[ ${ACTION} == check ]]; then - (( PRINTLEVEL-- )) - print_okay 'Already up to date' - return 0 - else - on_pull && print_okay 'Already up to date' - return ${?} - fi - fi - if [[ ${ACTION} == check ]]; then - print_okay 'Update available' - return 0 - fi - TO_REV=${REV} - fi - LOG=$(command git -C ${DIR} log --graph --color --format='%C(yellow)%h%C(reset) %s %C(cyan)(%cr)%C(reset)' ..${TO_REV} -- 2>/dev/null) - if ! ERR=$(command git -C ${DIR} checkout -q ${REV} -- 2>&1); then - print_error 'Error during git checkout' ${ERR} - return 1 - fi - if [[ ${TYPE} == branch ]]; then - if ! OUT=$(command git -C ${DIR} merge --ff-only --no-progress -n 2>&1); then - print_error 'Error during git merge' ${OUT} - return 1 - fi - # keep just first line of OUT - OUT=${OUT%%($'\n'|$'\r')*} - else - OUT="Updating to ${TYPE} ${REV}" - fi - if (( SUBMODULES )); then - if ! ERR=$(command git -C ${DIR} submodule update --init --recursive -q -- 2>&1); then - print_error 'Error during git submodule update' ${ERR} - return 1 - fi - fi - on_pull && print_okay ${OUT} ${LOG} - ;; -esac diff --git a/src/zimfw.zsh.erb b/src/zimfw.zsh.erb index c38ff9c..b2d1348 100644 --- a/src/zimfw.zsh.erb +++ b/src/zimfw.zsh.erb @@ -31,16 +31,6 @@ class Zim def render_commented(filename) render(filename).gsub(/^(?=.)/, "# ").gsub(/^$/, "#") end - - def render_escaped(filename) - render(filename).gsub(/(?=\$[^']|"|`)/, "\\\\").gsub(/#\{/, "$\{") - end - - def render_tools(pattern, var) - Dir[pattern].sort.map { |filename| - " #{File.basename(filename, ".zsh.erb")}) #{var}=\"#{render_escaped(filename)}\" ;;" - }.join("\n") - end end zim = Zim.new %># AUTOMATICALLY GENERATED FILE. EDIT ONLY THE SOURCE FILES AND THEN COMPILE. diff --git a/zimfw.zsh b/zimfw.zsh index 7d653d0..4725340 100644 --- a/zimfw.zsh +++ b/zimfw.zsh @@ -102,8 +102,7 @@ _zimfw_build_login_init() { command mv -f ${ztarget}{,.old} || return 1 fi _zimfw_mv =( - print -nR "# Do nothing. This file is deprecated. -" + print '# Do nothing. This file is deprecated.' ) ${ztarget} } @@ -434,7 +433,7 @@ _zimfw_compile() { } _zimfw_info() { - print -R 'zimfw version: '${_zversion}' (built at 2023-03-26 21:48:32 UTC, previous commit is 903e0e5)' + print -R 'zimfw version: '${_zversion}' (built at 2023-03-28 12:56:15 UTC, previous commit is 312b08c)' local zparam for zparam in LANG ${(Mk)parameters:#LC_*} OSTYPE TERM TERM_PROGRAM TERM_PROGRAM_VERSION ZIM_HOME ZSH_VERSION; do print -R ${(r.22....:.)zparam}${(P)zparam} @@ -519,346 +518,325 @@ _zimfw_run_list() { fi } -_zimfw_run_tool() { - local -r zname=${1} - if [[ -z ${_zurls[${zname}]} ]]; then - if (( _zprintlevel > 1 )) print -PR $'\E[2K\r'"%F{green})%f %B${zname}:%b Skipping external module" - return 0 - fi - if (( _zfrozens[${zname}] )); then - if (( _zprintlevel > 1 )) print -PR $'\E[2K\r'"%F{green})%f %B${zname}:%b Skipping frozen module" - return 0 - fi - case ${_zargs_action} in - install) - if [[ -e ${_zdirs[${zname}]} ]]; then - if (( _zprintlevel > 1 )) print -PR $'\E[2K\r'"%F{green})%f %B${zname}:%b Skipping already installed module" - return 0 - fi - _zimfw_print -nR $'\E[2K\r'"Installing ${zname} ..." - ;; - check|update) - if [[ ! -d ${_zdirs[${zname}]} ]]; then - print -u2 -PR $'\E[2K\r'"%F{red}x %B${zname}:%b Not installed. Run %Bzimfw install%b to install.%f" - return 1 - fi - if [[ ${_zargs_action} == check ]]; then - if (( _zprintlevel > 1 )) print -nR $'\E[2K\r'"Checking ${zname} ..." - else - _zimfw_print -nR $'\E[2K\r'"Updating ${zname} ..." - fi - ;; - *) - print -u2 -PR $'\E[2K\r'"%F{red}x %B${zname}:%b Unknown action ${_zargs_action}%f" - return 1 - ;; - esac - local zcmd - case ${_ztools[${zname}]} in - degit) zcmd="# This runs in a new shell -builtin emulate -L zsh -o EXTENDED_GLOB -integer PRINTLEVEL=\${1} -readonly -i SUBMODULES=\${8} -readonly ACTION=\${2} MODULE=\${3} DIR=\${4} URL=\${5} REV=\${7} ONPULL=\${9} TEMP=.zdegit_\${sysparams[pid]} -readonly TARBALL_TARGET=\${DIR}/\${TEMP}_tarball.tar.gz INFO_TARGET=\${DIR}/.zdegit - -print_error() { - print -u2 -PlR $'\E[2K\r'\"%F{red}x %B\${MODULE}:%b \${1}%f\" \${2:+\${(F):- \${(f)^2}}} +_zimfw_print_error() { + print -u2 -PlR $'\E[2K\r'"%F{red}x %B${_zname}:%b ${1}%f" ${2:+${(F):- ${(f)^2}}} } -print_okay() { - if (( PRINTLEVEL > 0 )); then - local -r log=\${2:+\${(F):- \${(f)^2}}} - if [[ \${SUBMODULES} -ne 0 && -e \${DIR}/.gitmodules ]]; then - print -u2 -PlR $'\E[2K\r'\"%F{yellow}! %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} - else - print -PlR $'\E[2K\r'\"%F{green})%f %B\${MODULE}:%b \${1}\" \${log} +_zimfw_print_okay() { + if (( _zprintlevel > ${2:-0} )) print -PlR $'\E[2K\r'"%F{green})%f %B${_zname}:%b ${1}" ${3:+${(F):- ${(f)^3}}} +} + +_zimfw_pull_print_okay() { + if [[ -n ${zonpull} ]]; then + local zerr + if ! zerr=$(builtin cd -q ${zdir} 2>&1 && builtin eval ${zonpull} 2>&1); then + _zimfw_print_error 'Error during on-pull' ${zerr} + return 1 + elif [[ ${_zprintlevel} -gt 1 && -n ${zerr} ]]; then + # Overrides ${3} to include the on-pull output, to be used by _zimfw_print_okay below. + builtin set ${1} ${2:-0} ${3:+${3}$'\n'}'On-pull output:'$'\n'${zerr} fi fi + _zimfw_print_okay "${@}" } -on_pull() { - if [[ -n \${ONPULL} ]]; then - if ! ERR=\$(builtin cd -q \${DIR} 2>&1 && builtin eval \${ONPULL} 2>&1); then - print_error 'Error during on-pull' \${ERR} - return 1 - elif [[ \${PRINTLEVEL} -gt 1 && -n \${ERR} ]]; then - builtin set \${1} \${2:+\${2}$'\n'}\"On-pull output:\"$'\n'\${ERR} - fi - fi -} - -download_tarball() { +_zimfw_download_tarball() { local host repo - if [[ \${URL} =~ ^([^:@/]+://)?([^@]+@)?([^:/]+)[:/]([^/]+/[^/]+)/?\$ ]]; then - host=\${match[3]} - repo=\${match[4]%.git} + if [[ ${zurl} =~ ^([^:@/]+://)?([^@]+@)?([^:/]+)[:/]([^/]+/[^/]+)/?$ ]]; then + host=${match[3]} + repo=${match[4]%.git} fi - if [[ \${host} != github.com || -z \${repo} ]]; then - print_error \"\${URL} is not a valid GitHub URL. Will not try to \${ACTION}.\" + if [[ ${host} != github.com || -z ${repo} ]]; then + _zimfw_print_error "${zurl} is not a valid GitHub zurl. Will not try to ${_zaction}." return 1 fi - local -r headers_target=\${DIR}/\${TEMP}_headers + local -r headers_target=${zdir}/${ztemp}_headers { - local info_header header etag - 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}.\" + local info_header header etag zerr + if [[ -r ${zinfo_target} ]]; then + local -r info=("${(@f)"$(<${zinfo_target})"}") + if [[ ${zurl} != ${info[1]} ]]; then + _zimfw_print_error "zurl does not match. Expected ${zurl}. Will not try to ${_zaction}." return 1 fi - # Previous REV is in line 2, reserved for future use. - info_header=\${info[3]} + # Previous zrev is in line 2, reserved for future use. + info_header=${info[3]} fi - local -r tarball_url=https://api.github.com/repos/\${repo}/tarball/\${REV} - if [[ \${ACTION} == check ]]; then - if [[ -z \${info_header} ]] return 0 - if (( \${+commands[curl]} )); then - command curl -IfsL -H \${info_header} \${tarball_url} >\${headers_target} + local -r tarball_url=https://api.github.com/repos/${repo}/tarball/${zrev} + if [[ ${_zaction} == check ]]; then + if [[ -z ${info_header} ]] return 0 + if (( ${+commands[curl]} )); then + command curl -IfsL -H ${info_header} ${tarball_url} >${headers_target} else - command wget --spider -qS --header=\${info_header} \${tarball_url} 2>\${headers_target} + command wget --spider -qS --header=${info_header} ${tarball_url} 2>${headers_target} fi else - if (( \${+commands[curl]} )); then - if ! ERR=\$(command curl -fsSL \${info_header:+-H} \${info_header} -o \${TARBALL_TARGET} -D \${headers_target} \${tarball_url} 2>&1); then - print_error \"Error downloading \${tarball_url} with curl\" \${ERR} + if (( ${+commands[curl]} )); then + if ! zerr=$(command curl -fsSL ${info_header:+-H} ${info_header} -o ${ztarball_target} -D ${headers_target} ${tarball_url} 2>&1); then + _zimfw_print_error "Error downloading ${tarball_url} with curl" ${zerr} return 1 fi else # wget returns 8 when 304 Not Modified, so we cannot use wget's error codes - command wget -qS \${info_header:+--header=\${info_header}} -O \${TARBALL_TARGET} \${tarball_url} 2>\${headers_target} + command wget -qS ${info_header:+--header=${info_header}} -O ${ztarball_target} ${tarball_url} 2>${headers_target} fi fi local -i http_code while IFS= read -r header; do - header=\${\${header## ##}%%$'\r'##} - if [[ \${header} == HTTP/* ]]; then - http_code=\${\${(s: :)header}[2]} - elif [[ \${\${(L)header%%:*}%% ##} == etag ]]; then - etag=\${\${header#*:}## ##} + header=${${header## ##}%%$'\r'##} + if [[ ${header} == HTTP/* ]]; then + http_code=${${(s: :)header}[2]} + elif [[ ${${(L)header%%:*}%% ##} == etag ]]; then + etag=${${header#*:}## ##} fi - done < \${headers_target} + done < ${headers_target} if (( http_code == 304 )); then # Not Modified - command rm -f \${TARBALL_TARGET} 2>/dev/null + command rm -f ${ztarball_target} 2>/dev/null return 0 elif (( http_code != 200 )); then - print_error \"Error downloading \${tarball_url}, HTTP code \${http_code}\" + _zimfw_print_error "Error downloading ${tarball_url}, HTTP code ${http_code}" return 1 fi - if [[ -z \${etag} ]]; then - print_error \"Error downloading \${tarball_url}, no ETag header found in response\" + if [[ -z ${etag} ]]; then + _zimfw_print_error "Error downloading ${tarball_url}, no ETag header found in response" return 1 fi - if [[ \${ACTION} == check ]]; then - command touch \${TARBALL_TARGET} # Update available + if [[ ${_zaction} == check ]]; then + command touch ${ztarball_target} # Update available else - if ! print -lR \"\${URL}\" \"\${REV}\" \"If-None-Match: \${etag}\" >! \${INFO_TARGET} 2>/dev/null; then - print_error \"Error creating or updating \${INFO_TARGET}\" + if ! print -lR "${zurl}" "${zrev}" "If-None-Match: ${etag}" >! ${zinfo_target} 2>/dev/null; then + _zimfw_print_error "Error creating or updating ${zinfo_target}" return 1 fi fi } always { - command rm -f \${headers_target} 2>/dev/null + 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} +_zimfw_untar_tarball() { + local zerr + if ! zerr=$(command tar -C ${1} --strip=1 -xzf ${ztarball_target} 2>&1); then + _zimfw_print_error "Error extracting ${ztarball_target}" ${zerr} return 1 fi } -create_dir() { - if ! ERR=\$(command mkdir -p \${1} 2>&1); then - print_error \"Error creating \${1}\" \${ERR} +_zimfw_create_dir() { + local zerr + if ! zerr=$(command mkdir -p ${1} 2>&1); then + _zimfw_print_error "Error creating ${1}" ${zerr} return 1 fi } -case \${ACTION} in - install) - { - create_dir \${DIR} && download_tarball && untar_tarball \${DIR} && on_pull && print_okay Installed - } always { - # return 1 does not change \${TRY_BLOCK_ERROR}, only changes \${?} - (( TRY_BLOCK_ERROR = ? )) - command rm -f \${TARBALL_TARGET} 2>/dev/null - if (( TRY_BLOCK_ERROR )) command rm -rf \${DIR} 2>/dev/null - } - ;; - check|update) - if [[ ! -r \${INFO_TARGET} ]]; then - if (( PRINTLEVEL > 0 )); then - print -u2 -PR $'\E[2K\r'\"%F{yellow}! %B\${MODULE}:%b Module was not installed using Zim's degit. Will not try to \${ACTION}. Use zmodule option %B-z%b|%B--frozen%b to disable this warning.%f\" - fi - return 0 - fi - readonly DIR_NEW=\${DIR}\${TEMP} - { - download_tarball || return 1 - if [[ \${ACTION} == check ]]; then - if [[ -e \${TARBALL_TARGET} ]]; then - print_okay 'Update available' - else - (( PRINTLEVEL-- )) - print_okay 'Already up to date' - fi - else - if [[ ! -e \${TARBALL_TARGET} ]]; then - on_pull && print_okay 'Already up to date' - return \${?} - 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} - return 1 - fi - on_pull && print_okay Updated \${LOG} - fi - } always { - command rm -f \${TARBALL_TARGET} 2>/dev/null - command rm -rf \${DIR_NEW} 2>/dev/null - } - ;; -esac -" ;; - git) zcmd="# This runs in a new shell -builtin emulate -L zsh -integer PRINTLEVEL=\${1} -readonly -i SUBMODULES=\${8} -readonly ACTION=\${2} MODULE=\${3} DIR=\${4} URL=\${5} TYPE=\${6} ONPULL=\${9} -REV=\${7} - -print_error() { - print -u2 -PlR $'\E[2K\r'\"%F{red}x %B\${MODULE}:%b \${1}%f\" \${2:+\${(F):- \${(f)^2}}} -} - -print_okay() { - if (( PRINTLEVEL > 0 )) print -PlR $'\E[2K\r'\"%F{green})%f %B\${MODULE}:%b \${1}\" \${2:+\${(F):- \${(f)^2}}} -} - -on_pull() { - if [[ -n \${ONPULL} ]]; then - if ! ERR=\$(builtin cd -q \${DIR} 2>&1 && builtin eval \${ONPULL} 2>&1); then - print_error 'Error during on-pull' \${ERR} - return 1 - elif [[ \${PRINTLEVEL} -gt 1 && -n \${ERR} ]]; then - builtin set \${1} \${2:+\${2}$'\n'}'On-pull output:'$'\n'\${ERR} - fi - fi -} - -case \${ACTION} in - install) - if ERR=\$(command git clone \${REV:+-b} \${REV} -q --config core.autocrlf=false \${\${SUBMODULES:#0}:+--recursive} -- \${URL} \${DIR} 2>&1); then - on_pull && print_okay Installed - else - print_error 'Error during git clone' \${ERR} - return 1 - fi - ;; - check|update) - if [[ ! -r \${DIR}/.git ]]; then - if (( PRINTLEVEL > 0 )); then - print -u2 -PR $'\E[2K\r'\"%F{yellow}! %B\${MODULE}:%b Module was not installed using git. Will not try to \${ACTION}. Use zmodule option %B-z%b|%B--frozen%b to disable this warning.%f\" - fi - return 0 - fi - if [[ \${URL} != \$(command git -C \${DIR} config --get remote.origin.url) ]]; then - print_error \"URL does not match. Expected \${URL}. Will not try to \${ACTION}.\" - return 1 - fi - if ! ERR=\$(command git -C \${DIR} fetch -pqt origin 2>&1); then - print_error 'Error during git fetch' \${ERR} - return 1 - fi - if [[ \${TYPE} == branch ]]; then - if [[ -z \${REV} ]]; then - # Get HEAD remote branch - if ! ERR=\$(command git -C \${DIR} remote set-head origin -a 2>&1); then - print_error 'Error during git remote set-head' \${ERR} - return 1 - fi - if REV=\$(command git -C \${DIR} symbolic-ref --short refs/remotes/origin/HEAD 2>&1); then - REV=\${REV#origin/} - else - print_error 'Error during git symbolic-ref' \${REV} - return 1 - fi - fi - TO_REV=\${REV}@{u} - if [[ \${ACTION} == check ]]; then - local -ri behind=\$(command git -C \${DIR} rev-list --count \${REV}..\${TO_REV} -- 2>/dev/null) - if (( behind )); then - print_okay \"Update available [behind \${behind}]\" - else - (( PRINTLEVEL-- )) - print_okay 'Already up to date' +_zimfw_tool_degit() { + local -ri zsubmodules=${5} + local -r zdir=${1} zurl=${2} zrev=${4} zonpull=${6} ztemp=.zdegit_${sysparams[pid]} + local -r ztarball_target=${zdir}/${ztemp}_tarball.tar.gz zinfo_target=${zdir}/.zdegit + case ${_zaction} in + install) + { + _zimfw_create_dir ${zdir} && _zimfw_download_tarball && _zimfw_untar_tarball ${zdir} && _zimfw_pull_print_okay Installed || return 1 + } always { + # return 1 does not change ${TRY_BLOCK_ERROR}, only changes ${?} + (( TRY_BLOCK_ERROR = ? )) + command rm -f ${ztarball_target} 2>/dev/null + if (( TRY_BLOCK_ERROR )) command rm -rf ${zdir} 2>/dev/null + } + ;; + check|update) + if [[ ! -r ${zinfo_target} ]]; then + if (( _zprintlevel > 0 )); then + print -u2 -PR $'\E[2K\r'"%F{yellow}! %B${_zname}:%b Module was not installed using Zim's degit. Will not try to ${_zaction}. Use zmodule option %B-z%b|%B--frozen%b to disable this warning.%f" fi return 0 fi - else - if [[ \${REV} == \$(command git -C \${DIR} describe --tags --exact-match 2>/dev/null) ]]; then - if [[ \${ACTION} == check ]]; then - (( PRINTLEVEL-- )) - print_okay 'Already up to date' + readonly zdir_new=${zdir}${ztemp} + { + local zerr zlog + _zimfw_download_tarball || return 1 + if [[ ${_zaction} == check ]]; then + if [[ -e ${ztarball_target} ]]; then + _zimfw_print_okay 'Update available' + return 4 + fi + _zimfw_print_okay 'Already up to date' 1 return 0 else - on_pull && print_okay 'Already up to date' - return \${?} + if [[ -e ${ztarball_target} ]]; then + _zimfw_create_dir ${zdir_new} && _zimfw_untar_tarball ${zdir_new} || return 1 + if (( ${+commands[diff]} )); then + zlog=$(command diff -x '.zdegit*' -x '*.zwc' -x '*.zwc.old' -qr ${zdir} ${zdir_new} 2>/dev/null) + zlog=${${zlog//${zdir_new}/new}//${zdir}/old} + fi + if ! zerr=$({ command cp -f ${zinfo_target} ${zdir_new} && \ + command rm -rf ${zdir} && command mv -f ${zdir_new} ${zdir} } 2>&1); then + _zimfw_print_error "Error updating ${zdir}" ${zerr} + return 1 + fi + _zimfw_pull_print_okay Updated 0 ${zlog} || return 1 + else + _zimfw_pull_print_okay 'Already up to date' || return 1 + fi fi + } always { + command rm -f ${ztarball_target} 2>/dev/null + command rm -rf ${zdir_new} 2>/dev/null + } + ;; + esac + # Check after successful install or update + if [[ ${_zprintlevel} -gt 0 && ${zsubmodules} -ne 0 && -e ${zdir}/.gitmodules ]]; then + print -u2 -PR $'\E[2K\r'"%F{yellow}! %B${_zname}:%b Module contains git submodules, which are not supported by Zim's degit. Use zmodule option %B--no-submodules%b to disable this warning.%f" + fi +} + +_zimfw_tool_git() { + local -ri zsubmodules=${5} + local -r zdir=${1} zurl=${2} ztype=${3} zonpull=${6} + local zrev=${4} ztorev zerr zout zlog + case ${_zaction} in + install) + if zerr=$(command git clone ${zrev:+-b} ${zrev} -q --config core.autocrlf=false ${${zsubmodules:#0}:+--recursive} -- ${zurl} ${zdir} 2>&1); then + _zimfw_pull_print_okay Installed + else + _zimfw_print_error 'Error during git clone' ${zerr} + return 1 fi - if [[ \${ACTION} == check ]]; then - print_okay 'Update available' + ;; + check|update) + if [[ ! -r ${zdir}/.git ]]; then + if (( _zprintlevel > 0 )); then + print -u2 -PR $'\E[2K\r'"%F{yellow}! %B${_zname}:%b Module was not installed using git. Will not try to ${_zaction}. Use zmodule option %B-z%b|%B--frozen%b to disable this warning.%f" + fi return 0 fi - TO_REV=\${REV} - fi - LOG=\$(command git -C \${DIR} log --graph --color --format='%C(yellow)%h%C(reset) %s %C(cyan)(%cr)%C(reset)' ..\${TO_REV} -- 2>/dev/null) - if ! ERR=\$(command git -C \${DIR} checkout -q \${REV} -- 2>&1); then - print_error 'Error during git checkout' \${ERR} - return 1 - fi - if [[ \${TYPE} == branch ]]; then - if ! OUT=\$(command git -C \${DIR} merge --ff-only --no-progress -n 2>&1); then - print_error 'Error during git merge' \${OUT} + if [[ ${zurl} != $(command git -C ${zdir} config --get remote.origin.url) ]]; then + _zimfw_print_error "zurl does not match. Expected ${zurl}. Will not try to ${_zaction}." return 1 fi - # keep just first line of OUT - OUT=\${OUT%%($'\n'|$'\r')*} - else - OUT=\"Updating to \${TYPE} \${REV}\" - fi - if (( SUBMODULES )); then - if ! ERR=\$(command git -C \${DIR} submodule update --init --recursive -q -- 2>&1); then - print_error 'Error during git submodule update' \${ERR} + if ! zerr=$(command git -C ${zdir} fetch -pqt origin 2>&1); then + _zimfw_print_error 'Error during git fetch' ${zerr} return 1 fi - fi - on_pull && print_okay \${OUT} \${LOG} - ;; -esac -" ;; + if [[ ${ztype} == branch ]]; then + if [[ -z ${zrev} ]]; then + # Get HEAD remote branch + if ! zerr=$(command git -C ${zdir} remote set-head origin -a 2>&1); then + _zimfw_print_error 'Error during git remote set-head' ${zerr} + return 1 + fi + if zrev=$(command git -C ${zdir} symbolic-ref --short refs/remotes/origin/HEAD 2>&1); then + zrev=${zrev#origin/} + else + _zimfw_print_error 'Error during git symbolic-ref' ${zrev} + return 1 + fi + fi + ztorev=${zrev}@{u} + if [[ ${_zaction} == check ]]; then + local -ri behind=$(command git -C ${zdir} rev-list --count ${zrev}..${ztorev} -- 2>/dev/null) + if (( behind )); then + _zimfw_print_okay "Update available [behind ${behind}]" + return 4 + else + _zimfw_print_okay 'Already up to date' 1 + return 0 + fi + fi + else + if [[ ${zrev} == $(command git -C ${zdir} describe --tags --exact-match 2>/dev/null) ]]; then + if [[ ${_zaction} == check ]]; then + _zimfw_print_okay 'Already up to date' 1 + return 0 + else + _zimfw_pull_print_okay 'Already up to date' + return ${?} + fi + fi + if [[ ${_zaction} == check ]]; then + _zimfw_print_okay 'Update available' + return 4 + fi + ztorev=${zrev} + fi + zlog=$(command git -C ${zdir} log --graph --color --format='%C(yellow)%h%C(reset) %s %C(cyan)(%cr)%C(reset)' ..${ztorev} -- 2>/dev/null) + if ! zerr=$(command git -C ${zdir} checkout -q ${zrev} -- 2>&1); then + _zimfw_print_error 'Error during git checkout' ${zerr} + return 1 + fi + if [[ ${ztype} == branch ]]; then + if ! zout=$(command git -C ${zdir} merge --ff-only --no-progress -n 2>&1); then + _zimfw_print_error 'Error during git merge' ${zout} + return 1 + fi + # keep just first line of zout + zout=${zout%%($'\n'|$'\r')*} + else + zout="Updating to ${ztype} ${zrev}" + fi + if (( zsubmodules )); then + if ! zerr=$(command git -C ${zdir} submodule update --init --recursive -q -- 2>&1); then + _zimfw_print_error 'Error during git submodule update' ${zerr} + return 1 + fi + fi + _zimfw_pull_print_okay ${zout} 0 ${zlog} + ;; + esac +} + +_zimfw_run_tool() { + local -r _zname=${1} + if [[ -z ${_zurls[${_zname}]} ]]; then + _zimfw_print_okay 'Skipping external module' 1 + return 0 + fi + if (( _zfrozens[${_zname}] )); then + _zimfw_print_okay 'Skipping frozen module' 1 + return 0 + fi + case ${_zaction} in + install) + if [[ -e ${_zdirs[${_zname}]} ]]; then + _zimfw_print_okay 'Skipping already installed module' 1 + return 0 + fi + _zimfw_print -nR $'\E[2K\r'"Installing ${_zname} ..." + ;; + check|update) + if [[ ! -d ${_zdirs[${_zname}]} ]]; then + _zimfw_print_error 'Not installed. Run %Bzimfw install%b to install.' + return 1 + fi + if [[ ${_zaction} == check ]]; then + if (( _zprintlevel > 1 )) print -nR $'\E[2K\r'"Checking ${_zname} ..." + else + _zimfw_print -nR $'\E[2K\r'"Updating ${_zname} ..." + fi + ;; *) - print -u2 -PR "$'\E[2K\r'%F{red}x %B${zname}:%b Unknown tool ${_ztools[${zname}]}%f" + _zimfw_print_error "Unknown action ${_zaction}" + return 1 + ;; + esac + local -r ztool=${_ztools[${_zname}]} + case ${ztool} in + degit|git) + _zimfw_tool_${ztool} "${_zdirs[${_zname}]}" "${_zurls[${_zname}]}" "${_ztypes[${_zname}]}" "${_zrevs[${_zname}]}" "${_zsubmodules[${_zname}]}" "${_zonpulls[${_zname}]}" + ;; + *) + _zimfw_print_error "Unknown tool ${ztool}" return 1 ;; esac - zsh -c ${zcmd} ${_ztools[${zname}]} "${_zprintlevel}" "${_zargs_action}" "${zname}" "${_zdirs[${zname}]}" "${_zurls[${zname}]}" "${_ztypes[${zname}]}" "${_zrevs[${zname}]}" "${_zsubmodules[${zname}]}" "${_zonpulls[${zname}]}" } _zimfw_run_tool_action() { - local -r _zargs_action=${1} - zargs -n 1 -P 0 -- "${_znames[@]}" -- _zimfw_run_tool - # Ignore return from zargs with -P. Was missing values before zsh 5.9, and - # it's intermittently failing in zsh 5.9 and macOS. See https://www.zsh.org/mla/workers/2022/msg00611.html + local -r _zaction=${1} + _zimfw_source_zimrc 1 && zargs -n 1 -P 0 -- "${_znames[@]}" -- _zimfw_run_tool return 0 } @@ -936,22 +914,22 @@ Options: ;; check) _zrestartmsg= - _zimfw_source_zimrc 3 && _zimfw_run_tool_action ${1} || return 1 + _zimfw_run_tool_action ${1} || return 1 (( _zprintlevel-- )) _zimfw_print -PR "Done with ${1}." # Only printed in verbose mode ;; init) _zrestartmsg= - _zimfw_source_zimrc 3 && _zimfw_run_tool_action install || return 1 + _zimfw_run_tool_action install || return 1 (( _zprintlevel-- )) _zimfw_print -PR "Done with install." # Only printed in verbose mode - _zimfw_build && _zimfw_compile + _zimfw_source_zimrc 2 && _zimfw_build && _zimfw_compile ;; install|update) - _zimfw_source_zimrc 3 && _zimfw_run_tool_action ${1} || return 1 + _zimfw_run_tool_action ${1} || return 1 _zimfw_print -PR "Done with ${1}.${_zrestartmsg}" (( _zprintlevel-- )) - _zimfw_build && _zimfw_compile + _zimfw_source_zimrc 2 && _zimfw_build && _zimfw_compile ;; uninstall) _zimfw_source_zimrc 2 && _zimfw_list_unuseds && _zimfw_uninstall ;; check-version) _zimfw_check_version 1 ;; diff --git a/zimfw.zsh.gz b/zimfw.zsh.gz new file mode 100644 index 0000000000000000000000000000000000000000..695cbf8846d1e8f73fc3cad65cd9b2d8aa62d206 GIT binary patch literal 10245 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