diff --git a/CHANGELOG.md b/CHANGELOG.md index 850b22a..f83b567 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- `reinstall` action, that removes and then installs again the modules that + failed any of the checks: + - module was installed with the defined tool, + - module URL matches the defined one. + ### Changed - Ask before uninstalling each unused module, instead of asking just once for diff --git a/src/stage2/20_guard.zsh.erb b/src/stage2/20_guard.zsh.erb index accde4b..5001883 100644 --- a/src/stage2/20_guard.zsh.erb +++ b/src/stage2/20_guard.zsh.erb @@ -1,5 +1,5 @@ autoload -Uz is-at-least && if ! is-at-least <%= min_zsh_version %>; then - print -u2 -R $'<%= red %>'${0}$': Error starting zimfw. You\'re using Zsh version <%= bold %>'${ZSH_VERSION}$'<%= normalred %> and versions < <%= bold %><%= min_zsh_version %><%= normalred %> are not supported. Upgrade your Zsh.<%= normal %>' + print -u2 -R $'<%= red %>'${0}$': Error starting zimfw. You\'re using Zsh version <%= bold %>'${ZSH_VERSION}$'<%= normalred %> and versions < <%= bold %><%= min_zsh_version %><%= normalred %> are not supported. Update your Zsh.<%= normal %>' return 1 fi autoload -Uz zargs diff --git a/src/stage2/75_zimfw_tool_degit.zsh.erb b/src/stage2/75_zimfw_tool_degit.zsh.erb index 83f5a86..b0a11d6 100644 --- a/src/stage2/75_zimfw_tool_degit.zsh.erb +++ b/src/stage2/75_zimfw_tool_degit.zsh.erb @@ -84,15 +84,17 @@ _zimfw_tool_degit() { readonly ACTION=${1} DIR=${2} URL=${3} REV=${5} ONPULL=${7} TEMP=.zdegit_${sysparams[pid]} readonly TARBALL_TARGET=${DIR}/${TEMP}_tarball.tar.gz INFO_TARGET=${DIR}/.zdegit case ${ACTION} in - pre) + pre|prereinstall) + local premsg + if [[ ${ACTION} == pre ]] premsg=$' Use zmodule option <%= bold %>-z<%= normalred %>|<%= bold %>--frozen<%= normalred %> to disable this error or run <%= bold %>zimfw reinstall<%= normalred %> to reinstall.' if [[ -e ${DIR} ]]; then if [[ ! -r ${INFO_TARGET} ]]; then - _zimfw_print_error $'Module was not installed using zimfw\'s degit. Use zmodule option <%= bold %>-z<%= normalred %>|<%= bold %>--frozen<%= normalred %> to disable this error.' + _zimfw_print_error $'Module was not installed using zimfw\'s degit.'${premsg} return 1 fi readonly INFO=("${(@f)"$(<${INFO_TARGET})"}") if [[ ${URL} != ${INFO[1]} ]]; then - _zimfw_print_error 'The zimfw degit URL does not match. Expected '${URL}$'. Use zmodule option <%= bold %>-z<%= normalred %>|<%= bold %>--frozen<%= normalred %> to disable this error.' + _zimfw_print_error 'The zimfw degit URL does not match. Expected '${URL}.${premsg} return 1 fi fi diff --git a/src/stage2/75_zimfw_tool_git.zsh.erb b/src/stage2/75_zimfw_tool_git.zsh.erb index 2d671b5..05990a0 100644 --- a/src/stage2/75_zimfw_tool_git.zsh.erb +++ b/src/stage2/75_zimfw_tool_git.zsh.erb @@ -4,14 +4,16 @@ _zimfw_tool_git() { readonly ACTION=${1} DIR=${2} URL=${3} TYPE=${4} ONPULL=${7} REV=${5} case ${ACTION} in - pre) + pre|prereinstall) + local premsg + if [[ ${ACTION} == pre ]] premsg=$' Use zmodule option <%= bold %>-z<%= normalred %>|<%= bold %>--frozen<%= normalred %> to disable this error or run <%= bold %>zimfw reinstall<%= normalred %> to reinstall.' if [[ -e ${DIR} ]]; then if [[ ! -r ${DIR}/.git ]]; then - _zimfw_print_error $'Module was not installed using git. Use zmodule option <%= bold %>-z<%= normalred %>|<%= bold %>--frozen<%= normalred %> to disable this error.' + _zimfw_print_error 'Module was not installed using git.'${premsg} return 1 fi if [[ ${URL} != $(command git -C ${DIR} config --get remote.origin.url) ]]; then - _zimfw_print_error 'The git URL does not match. Expected '${URL}.$' Use zmodule option <%= bold %>-z<%= normalred %>|<%= bold %>--frozen<%= normalred %> to disable this error.' + _zimfw_print_error 'The git URL does not match. Expected '${URL}.${premsg} return 1 fi fi diff --git a/src/stage2/75_zimfw_tool_mkdir.zsh.erb b/src/stage2/75_zimfw_tool_mkdir.zsh.erb index 214d488..480e52c 100644 --- a/src/stage2/75_zimfw_tool_mkdir.zsh.erb +++ b/src/stage2/75_zimfw_tool_mkdir.zsh.erb @@ -2,7 +2,7 @@ _zimfw_tool_mkdir() { # This runs in a subshell readonly -i SUBMODULES=${6} readonly ACTION=${1} DIR=${2} TYPE=${4} REV=${5} ONPULL=${7} - if [[ ${ACTION} == pre ]] return 0 + if [[ ${ACTION} == (pre|reinstall) ]] return 0 if [[ -n ${REV} ]]; then _zimfw_print_warn $'The zmodule option <%= bold %>-'${TYPE[1]}$'<%= normalyellow %>|<%= bold %>--'${TYPE}$'<%= normalyellow %> has no effect when using the mkdir tool' fi diff --git a/src/stage2/77_zimfw_run_tool.zsh.erb b/src/stage2/77_zimfw_run_tool.zsh.erb index 139ddeb..26fc442 100644 --- a/src/stage2/77_zimfw_run_tool.zsh.erb +++ b/src/stage2/77_zimfw_run_tool.zsh.erb @@ -1,5 +1,6 @@ _zimfw_run_tool() { - local -r _zname=${1} + local zaction=${1} + local -r _zname=${2} if [[ -z ${_zurls[${_zname}]} ]]; then _zimfw_print_okay 'Skipping external module' 1 return 0 @@ -14,8 +15,26 @@ _zimfw_run_tool() { return 1 fi set "${_zdirs[${_zname}]}" "${_zurls[${_zname}]}" "${_ztypes[${_zname}]}" "${_zrevs[${_zname}]}" "${_zsubmodules[${_zname}]}" "${_zonpulls[${_zname}]}" - _zimfw_tool_${ztool} pre "${@}" || return 1 - case ${_zaction} in + if [[ ${zaction} == reinstall ]]; then + _zimfw_tool_${ztool} prereinstall "${@}" && return 0 + if (( _zprintlevel <= 0 )); then + command rm -rf ${_zdirs[${_zname}]} || return 1 + else + local zopt + if (( _zprintlevel > 1 )) zopt=-v + if read -q "?Reinstall ${_zname} [y/N]? "; then + print + command rm -rf ${zopt} ${_zdirs[${_zname}]} || return 1 + else + print + return 0 + fi + fi + zaction=install + else + _zimfw_tool_${ztool} pre "${@}" || return 1 + fi + case ${zaction} in install) if [[ -e ${_zdirs[${_zname}]} ]]; then _zimfw_print_okay 'Skipping already installed module' 1 @@ -28,16 +47,16 @@ _zimfw_run_tool() { _zimfw_print_error $'Not installed. Run <%= bold %>zimfw install<%= normalred %> to install.' return 1 fi - if [[ ${_zaction} == check ]]; then + 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}" + _zimfw_print_error "Unknown action ${zaction}" return 1 ;; esac - _zimfw_tool_${ztool} ${_zaction} "${@}" + _zimfw_tool_${ztool} ${zaction} "${@}" } diff --git a/src/stage2/78_zimfw_run_tool_action.zsh.erb b/src/stage2/78_zimfw_run_tool_action.zsh.erb index 4ff1266..d51e69a 100644 --- a/src/stage2/78_zimfw_run_tool_action.zsh.erb +++ b/src/stage2/78_zimfw_run_tool_action.zsh.erb @@ -1,6 +1,7 @@ _zimfw_run_tool_action() { - local -r _zaction=${1} + local -i zmaxprocs=0 + if [[ ${1} == reinstall ]] zmaxprocs=1 _zimfw_source_zimrc 1 || return 1 - zargs -n 1 -P 0 -- "${_znames[@]}" -- _zimfw_run_tool + zargs -n 2 -P ${zmaxprocs} -- "${_znames[@]}" -- _zimfw_run_tool ${1} return 0 } diff --git a/src/stage2/80_zimfw.zsh.erb b/src/stage2/80_zimfw.zsh.erb index eaba1b7..40627f6 100644 --- a/src/stage2/80_zimfw.zsh.erb +++ b/src/stage2/80_zimfw.zsh.erb @@ -16,6 +16,9 @@ Actions: <%= bold %>init<%= normal %> Same as <%= bold %>install<%= normal %>, but with output tailored to be used at terminal startup. <%= bold %>install<%= normal %> Install new modules. Also does <%= bold %>build<%= normal %>, <%= bold %>compile<%= normal %>. Use <%= bold %>-v<%= normal %> to also see their output, any on-pull output and skipped modules. + <%= bold %>reinstall<%= normal %> Reinstall modules that failed check. Prompts for confirmation. Use <%= bold %>-q<%= normal %> for + quiet reinstall. Also does <%= bold %>build<%= normal %>, <%= bold %>compile<%= normal %>. Use <%= bold %>-v<%= normal %> to also see their output, + any on-pull output and skipped modules. <%= bold %>uninstall<%= normal %> Delete unused modules. Prompts for confirmation. Use <%= bold %>-q<%= normal %> for quiet uninstall. <%= bold %>check<%= normal %> Check if updates for current modules are available. Use <%= bold %>-v<%= normal %> to also see skipped and up to date modules. @@ -55,7 +58,7 @@ Options: _zimfw_check_version ${zversion_check_force} 1 fi - if [[ ! -w ${ZIM_HOME} && ${1} == (build|check|init|install|update|check-version) ]]; then + if [[ ! -w ${ZIM_HOME} && ${1} == (build|check|init|install|update|reinstall|check-version) ]]; then print -u2 -R $'<%= red %>'${0}$': No write permission to <%= bold %>'${ZIM_HOME}$'<%= normalred %>. Will not try to '${1}$'.<%= normal %>' return 1 fi @@ -90,7 +93,7 @@ Options: _zimfw_print 'Done with install.' # Only printed in verbose mode _zimfw_source_zimrc 2 && _zimfw_build && _zimfw_compile ;; - install|update) + install|update|reinstall) _zimfw_run_tool_action ${1} || return 1 _zimfw_print -R "Done with ${1}.${_zrestartmsg}" (( _zprintlevel-- )) diff --git a/zimfw.zsh b/zimfw.zsh index 8e0fd2b..0c6a5bc 100644 --- a/zimfw.zsh +++ b/zimfw.zsh @@ -25,7 +25,7 @@ # SOFTWARE. autoload -Uz is-at-least && if ! is-at-least 5.2; then - print -u2 -R $'\E[31m'${0}$': Error starting zimfw. You\'re using Zsh version \E[1m'${ZSH_VERSION}$'\E[0;31m and versions < \E[1m5.2\E[0;31m are not supported. Upgrade your Zsh.\E[0m' + print -u2 -R $'\E[31m'${0}$': Error starting zimfw. You\'re using Zsh version \E[1m'${ZSH_VERSION}$'\E[0;31m and versions < \E[1m5.2\E[0;31m are not supported. Update your Zsh.\E[0m' return 1 fi autoload -Uz zargs @@ -462,7 +462,7 @@ _zimfw_compile() { } _zimfw_info() { - print -R 'zimfw version: '${_zversion}' (built at 2024-09-16 23:27:18 UTC, previous commit is 3fe3ba2)' + print -R 'zimfw version: '${_zversion}' (built at 2024-10-07 13:45:47 UTC, previous commit is 869a8f5)' 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} @@ -680,15 +680,17 @@ _zimfw_tool_degit() { readonly ACTION=${1} DIR=${2} URL=${3} REV=${5} ONPULL=${7} TEMP=.zdegit_${sysparams[pid]} readonly TARBALL_TARGET=${DIR}/${TEMP}_tarball.tar.gz INFO_TARGET=${DIR}/.zdegit case ${ACTION} in - pre) + pre|prereinstall) + local premsg + if [[ ${ACTION} == pre ]] premsg=$' Use zmodule option \E[1m-z\E[0;31m|\E[1m--frozen\E[0;31m to disable this error or run \E[1mzimfw reinstall\E[0;31m to reinstall.' if [[ -e ${DIR} ]]; then if [[ ! -r ${INFO_TARGET} ]]; then - _zimfw_print_error $'Module was not installed using zimfw\'s degit. Use zmodule option \E[1m-z\E[0;31m|\E[1m--frozen\E[0;31m to disable this error.' + _zimfw_print_error $'Module was not installed using zimfw\'s degit.'${premsg} return 1 fi readonly INFO=("${(@f)"$(<${INFO_TARGET})"}") if [[ ${URL} != ${INFO[1]} ]]; then - _zimfw_print_error 'The zimfw degit URL does not match. Expected '${URL}$'. Use zmodule option \E[1m-z\E[0;31m|\E[1m--frozen\E[0;31m to disable this error.' + _zimfw_print_error 'The zimfw degit URL does not match. Expected '${URL}.${premsg} return 1 fi fi @@ -750,14 +752,16 @@ _zimfw_tool_git() { readonly ACTION=${1} DIR=${2} URL=${3} TYPE=${4} ONPULL=${7} REV=${5} case ${ACTION} in - pre) + pre|prereinstall) + local premsg + if [[ ${ACTION} == pre ]] premsg=$' Use zmodule option \E[1m-z\E[0;31m|\E[1m--frozen\E[0;31m to disable this error or run \E[1mzimfw reinstall\E[0;31m to reinstall.' if [[ -e ${DIR} ]]; then if [[ ! -r ${DIR}/.git ]]; then - _zimfw_print_error $'Module was not installed using git. Use zmodule option \E[1m-z\E[0;31m|\E[1m--frozen\E[0;31m to disable this error.' + _zimfw_print_error 'Module was not installed using git.'${premsg} return 1 fi if [[ ${URL} != $(command git -C ${DIR} config --get remote.origin.url) ]]; then - _zimfw_print_error 'The git URL does not match. Expected '${URL}.$' Use zmodule option \E[1m-z\E[0;31m|\E[1m--frozen\E[0;31m to disable this error.' + _zimfw_print_error 'The git URL does not match. Expected '${URL}.${premsg} return 1 fi fi @@ -846,7 +850,7 @@ _zimfw_tool_mkdir() { # This runs in a subshell readonly -i SUBMODULES=${6} readonly ACTION=${1} DIR=${2} TYPE=${4} REV=${5} ONPULL=${7} - if [[ ${ACTION} == pre ]] return 0 + if [[ ${ACTION} == (pre|reinstall) ]] return 0 if [[ -n ${REV} ]]; then _zimfw_print_warn $'The zmodule option \E[1m-'${TYPE[1]}$'\E[0;33m|\E[1m--'${TYPE}$'\E[0;33m has no effect when using the mkdir tool' fi @@ -859,7 +863,8 @@ _zimfw_tool_mkdir() { } _zimfw_run_tool() { - local -r _zname=${1} + local zaction=${1} + local -r _zname=${2} if [[ -z ${_zurls[${_zname}]} ]]; then _zimfw_print_okay 'Skipping external module' 1 return 0 @@ -874,8 +879,26 @@ _zimfw_run_tool() { return 1 fi set "${_zdirs[${_zname}]}" "${_zurls[${_zname}]}" "${_ztypes[${_zname}]}" "${_zrevs[${_zname}]}" "${_zsubmodules[${_zname}]}" "${_zonpulls[${_zname}]}" - _zimfw_tool_${ztool} pre "${@}" || return 1 - case ${_zaction} in + if [[ ${zaction} == reinstall ]]; then + _zimfw_tool_${ztool} prereinstall "${@}" && return 0 + if (( _zprintlevel <= 0 )); then + command rm -rf ${_zdirs[${_zname}]} || return 1 + else + local zopt + if (( _zprintlevel > 1 )) zopt=-v + if read -q "?Reinstall ${_zname} [y/N]? "; then + print + command rm -rf ${zopt} ${_zdirs[${_zname}]} || return 1 + else + print + return 0 + fi + fi + zaction=install + else + _zimfw_tool_${ztool} pre "${@}" || return 1 + fi + case ${zaction} in install) if [[ -e ${_zdirs[${_zname}]} ]]; then _zimfw_print_okay 'Skipping already installed module' 1 @@ -888,24 +911,25 @@ _zimfw_run_tool() { _zimfw_print_error $'Not installed. Run \E[1mzimfw install\E[0;31m to install.' return 1 fi - if [[ ${_zaction} == check ]]; then + if [[ ${zaction} == check ]]; then if (( _zprintlevel > 1 )) print -nR $'\E[2K\rChecking '${_zname}' ...' else _zimfw_print -nR $'\E[2K\rUpdating '${_zname}' ...' fi ;; *) - _zimfw_print_error "Unknown action ${_zaction}" + _zimfw_print_error "Unknown action ${zaction}" return 1 ;; esac - _zimfw_tool_${ztool} ${_zaction} "${@}" + _zimfw_tool_${ztool} ${zaction} "${@}" } _zimfw_run_tool_action() { - local -r _zaction=${1} + local -i zmaxprocs=0 + if [[ ${1} == reinstall ]] zmaxprocs=1 _zimfw_source_zimrc 1 || return 1 - zargs -n 1 -P 0 -- "${_znames[@]}" -- _zimfw_run_tool + zargs -n 2 -P ${zmaxprocs} -- "${_znames[@]}" -- _zimfw_run_tool ${1} return 0 } @@ -927,6 +951,9 @@ Actions: \E[1minit\E[0m Same as \E[1minstall\E[0m, but with output tailored to be used at terminal startup. \E[1minstall\E[0m Install new modules. Also does \E[1mbuild\E[0m, \E[1mcompile\E[0m. Use \E[1m-v\E[0m to also see their output, any on-pull output and skipped modules. + \E[1mreinstall\E[0m Reinstall modules that failed check. Prompts for confirmation. Use \E[1m-q\E[0m for + quiet reinstall. Also does \E[1mbuild\E[0m, \E[1mcompile\E[0m. Use \E[1m-v\E[0m to also see their output, + any on-pull output and skipped modules. \E[1muninstall\E[0m Delete unused modules. Prompts for confirmation. Use \E[1m-q\E[0m for quiet uninstall. \E[1mcheck\E[0m Check if updates for current modules are available. Use \E[1m-v\E[0m to also see skipped and up to date modules. @@ -966,7 +993,7 @@ Options: _zimfw_check_version ${zversion_check_force} 1 fi - if [[ ! -w ${ZIM_HOME} && ${1} == (build|check|init|install|update|check-version) ]]; then + if [[ ! -w ${ZIM_HOME} && ${1} == (build|check|init|install|update|reinstall|check-version) ]]; then print -u2 -R $'\E[31m'${0}$': No write permission to \E[1m'${ZIM_HOME}$'\E[0;31m. Will not try to '${1}$'.\E[0m' return 1 fi @@ -1001,7 +1028,7 @@ Options: _zimfw_print 'Done with install.' # Only printed in verbose mode _zimfw_source_zimrc 2 && _zimfw_build && _zimfw_compile ;; - install|update) + install|update|reinstall) _zimfw_run_tool_action ${1} || return 1 _zimfw_print -R "Done with ${1}.${_zrestartmsg}" (( _zprintlevel-- ))