zdharma-continuum.zinit/zinit-install.zsh
Vladislav Doster b8855c7887 feat(ziextract): support zst archive format
Signed-off-by: Vladislav Doster <mvdoster@gmail.com>
2026-09-01 17:22:49 -05:00

2474 lines
105 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4;
# -*-
# Copyright (c) 2016-2020 Sebastian Gniazdowski and contributors.
builtin source "${ZINIT[BIN_DIR]}/zinit-side.zsh" || {
builtin print -P "${ZINIT[col-error]}ERROR:%f%b Couldn't find ${ZINIT[col-obj]}zinit-side.zsh%f%b."
return 1
}
# FUNCTION: .zinit-jq-check [[[
# Check if jq is available and outputs an error message with instructions if
# that's not the case
.zinit-jq-check() {
command -v jq >/dev/null && return 0
+zi-log "{error}❌ ERROR: jq binary not found" \
"{nl}{u-warn}Please install jq:{rst}" \
"https://github.com/jqlang/jq" \
"{nl}{u-warn}To do so with zinit, please refer to:{rst}" \
"https://github.com/zdharma-continuum/zinit/wiki/%F0%9F%A7%8A-Recommended-ices#jq"
return 1
} # ]]]
# FUNCTION: .zinit-json-get-value [[[
# Wrapper around jq that return the value of a property
#
# $1: JSON structure
# $2: jq path
.zinit-json-get-value() {
.zinit-jq-check || return 1
local jsonstr=$1 jqpath=$2
jq -er ".${jqpath}" <<< "$jsonstr"
} # ]]]
# FUNCTION: .zinit-json-to-array [[[
# Wrapper around jq that sets key/values of an associative array, replicating
# the structure of a given JSON object
#
# $1: JSON structure
# $2: jq path
# $3: name of the associative array to store the key/value pairs in
.zinit-json-to-array() {
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt localoptions noglob
.zinit-jq-check || return 1
local jsonstr=$1 jqpath=$2 varname=$3
(( ${(P)+varname} )) || typeset -gA "$varname"
# NOTE We're not using @sh for the keys on purpose. Associative
# array keys are used verbatim by zsh:
# typeset -A a; a[key]=one; a['key']=two; echo ${(k)a}
# 'key' key
local evalstr=$(command jq -er --arg varname $varname \
'.'${jqpath}' | to_entries |
map($varname + "[\(.key)]=\(.value | @sh);")[]' \
<<< "$jsonstr")
eval "$evalstr"
} # ]]]
# FUNCTION: .zinit-get-package [[[
.zinit-get-package() {
.zinit-jq-check || return 1
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt extendedglob warncreateglobal typesetsilent noshortloops rcquotes
local user=$1 pkg=$2 plugin=$2 id_as=$3 dir=$4 profile=$5 \
ver=${ICE[ver]} local_path=${ZINIT[PLUGINS_DIR]}/${3//\//---} \
pkgjson tmpfile=${$(mktemp):-${TMPDIR:-/tmp}/zsh.xYzAbc123}
local URL=https://raw.githubusercontent.com/${ZINIT[PACKAGES_REPO]}/${ver:-${ZINIT[PACKAGES_BRANCH]}}/${pkg}/package.json
# Consume (i.e., delete) the ver ice to avoid being consumed again at git-clone time
[[ -n "$ver" ]] && unset 'ICE[ver]'
local pro_sep="{rst}, {profile}" epro_sep="{error}, {profile}" \
tool_sep="{rst}, {cmd}" \
lhi_hl="{lhi}" profile_hl="{profile}"
trap "rmdir ${(qqq)local_path} 2>/dev/null; return 1" INT TERM QUIT HUP
trap "rmdir ${(qqq)local_path} 2>/dev/null" EXIT
# Check if we were provided with a local path to a package.json
# as in:
# zinit pack'/zp/firefox-dev/package.json:default' for firefox-dev
if [[ $profile == ./* || $profile == /* ]] {
local localpkg=1
# FIXME below only works if there are no ':' in the path
tmpfile=${profile%:*}
profile=${${${(M)profile:#*:*}:+${profile#*:}}:-default}
} elif { ! .zinit-download-file-stdout $URL 0 1 2>/dev/null > $tmpfile } {
# retry
command rm -f $tmpfile
.zinit-download-file-stdout $URL 1 1 2>/dev/null >1 $tmpfile
}
# load json from file
[[ -e $tmpfile ]] && pkgjson="$(<$tmpfile)"
# Set package name (used later in the output)
local pkgname=${${id_as##_unknown}:-${pkg:-${plugin}}}
[[ -n "$localpkg" ]] && pkgname="{pid}$pkgname{rst} {note}[$tmpfile]{rst}"
if [[ -z $pkgjson ]] {
+zi-log "{error}❌ Error: the package {hi}${pkgname}" \
"{error}couldn't be found.{rst}"
return 1
}
# root field, where the relevant data is stored
local json_root='["zsh-data"]'
local json_ices="${json_root}[\"zinit-ices\"]"
local json_meta="${json_root}[\"plugin-info\"]"
local -a profiles
profiles=("${(@f)$(.zinit-json-get-value "$pkgjson" "${json_ices} | keys[]")}") \
|| return 1
# Check if user requested an unknown profile
if ! (( ${profiles[(I)${profile}]} )) {
# Assumption: the default profile is the first in the table (-> different color).
+zi-log "{u-warn}Error{b-warn}:{error} the profile {apo}\`{hi}$profile{apo}\`" \
"{error}couldn't be found, aborting. Available profiles are:" \
"{lhi}${(pj:$epro_sep:)profiles[@]}{error}.{rst}"
return 1
}
local json_profile="${json_ices}[\"${profile}\"]"
local -A metadata
.zinit-json-to-array "$pkgjson" "$json_meta" metadata
if [[ "$?" -ne 0 || -z "$metadata" ]] {
+zi-log '{error}❌ ERROR: Failed to retrieve metadata from package.json'
return 1
}
local user=${metadata[user]} plugin=${metadata[plugin]} \
message=${metadata[message]} url=${metadata[url]}
.zinit-json-to-array "$pkgjson" "$json_profile" ICE
local -a requirements
# FIXME requires shouldn't be stored under zinit-ices...
if [[ -n "$ICE[requires]" ]] {
# split requirements on ';'
requirements=(${(s.;.)${ICE[requires]}})
unset 'ICE[requires]'
}
[[ ${ICE[as]} == program ]] && ICE[as]="command"
[[ -n ${ICE[on-update-of]} ]] && ICE[subscribe]="${ICE[subscribe]:-${ICE[on-update-of]}}"
[[ -n ${ICE[pick]} ]] && ICE[pick]="${ICE[pick]//\$ZPFX/${ZPFX%/}}"
# FIXME Do we even need that? If yes, we may want to do that in
# .zinit-json-to-array
if [[ -n ${ICE[id-as]} ]] {
@zinit-substitute 'ICE[id-as]'
local -A map
map=( "\"" "\\\"" "\\" "\\" )
eval "ICE[id-as]=\"${ICE[id-as]//(#m)[\"\\]/${map[$MATCH]}}\""
}
+zi-log "{info3}Package{ehi}:{rst} ${pkgname}. Selected" \
"profile{ehi}:{rst} {hi}$profile{rst}. Available" \
"profiles:${${${(M)profile:#default}:+$lhi_hl}:-$profile_hl}" \
"${(pj:$pro_sep:)profiles[@]}{rst}."
if [[ $profile != *bgn* && -n ${(M)profiles[@]:#*bgn*} ]] {
+zi-log "{note}Note:{rst} The {apo}\`{profile}bgn{glob}*{apo}\`{rst}" \
"profiles (if any are available) are the recommended ones (the reason" \
"is that they expose the binaries provided by the package without" \
"altering (i.e.: {slight}cluttering{rst}{…}) the {var}\$PATH{rst}" \
"environment variable)."
}
local required
for required ( $requirements ) {
if [[ $required == (bgn|dl|monitor) ]]; then
if [[ ( $required == bgn && -z ${(k)ZINIT_EXTS[(r)<-> z-annex-data: zinit-annex-bin-gem-node *]} ) || \
( $required == dl && -z ${(k)ZINIT_EXTS[(r)<-> z-annex-data: zinit-annex-patch-dl *]} ) || \
( $required == monitor && -z ${(k)ZINIT_EXTS[(r)<-> z-annex-data: zinit-annex-readurl *]} )
]]; then
local -A namemap
namemap=( bgn bin-gem-node dl patch-dl monitor readurl )
+zi-log -n "{u-warn}ERROR{b-warn}: {error}the "
if [[ -z ${(MS)ICE[requires]##(\;|(#s))$required(\;|(#e))} ]]; then
+zi-log -n "{error}requested profile {apo}\`{hi}$profile{apo}\`{error} "
else
+zi-log -n "{error}package {pid}$pkg{error} "
fi
+zi-log '{error}requires the {apo}`{annex}'${namemap[$required]}'{apo}`' \
"{error}annex, which is currently not installed." \
"{nl}{nl}If you'd like to install it, you can visit its homepage:" \
"{nl} {url}https://github.com/zdharma-continuum/zinit-annex-${(L)namemap[$required]}{rst}" \
"{nl}for instructions."
(( ${#profiles[@]:#$profile} > 0 )) && \
+zi-log "{nl}Other available profiles are:" \
"{profile}${(pj:$pro_sep:)${profiles[@]:#$profile}}{rst}."
return 1
fi
else
if ! command -v $required &>/dev/null; then
+zi-log -n "{u-warn}ERROR{b-warn}: {error}the "
if [[ -n ${(MS)ICE[requires]##(\;|(#s))$required(\;|(#e))} ]]; then
+zi-log -n "{error}requested profile {apo}\`{hi}$profile{apo}\`{error} "
else
+zi-log -n "{error}package {pid}$pkg{error} "
fi
+zi-log '{error}requires a {apo}`{cmd}'$required'{apo}`{error}' \
"command to be available in {var}\$PATH{error}.{rst}" \
"{nl}{error}The package cannot be installed unless the" \
"command will be available."
(( ${#profiles[@]:#$profile} > 0 )) && \
+zi-log "{nl}Other available profiles are:" \
"{profile}${(pj:$pro_sep:)${profiles[@]:#$profile}}{rst}."
return 1
fi
fi
}
if [[ -n ${ICE[dl]} && -z ${(k)ZINIT_EXTS[(r)<-> z-annex-data: zinit-annex-patch-dl *]} ]] {
+zi-log "{nl}{u-warn}WARNING{b-warn}:{rst} the profile uses" \
"{ice}dl''{rst} ice however there's currently no {annex}zinit-annex-patch-dl{rst}" \
"annex loaded, which provides it."
+zi-log "The ice will be inactive, i.e.: no additional" \
"files will become downloaded (the ice downloads the given URLs)." \
"The package should still work, as it doesn't indicate to" \
"{u}{slight}require{rst} the annex."
+zi-log "{nl}You can download the" \
"annex from its homepage at {url}https://github.com/zdharma-continuum/zinit-annex-patch-dl{rst}."
}
[[ -n ${message} ]] && +zi-log "{info}${message}{rst}"
if (( ${+ICE[is-snippet]} )) {
reply=( "" "$url" )
REPLY=snippet
return 0
}
# FIXME This part below is a bit odd since it essentially replicates what
# the dl ice supposed to be doing.
# TL;DR below downloads whatever url is stored in the "_resolved" field
if (( !${+ICE[git]} && !${+ICE[from]} )) {
(
local -A jsondata
local URL=$(.zinit-json-get-value "$pkgjson" "_resolved")
local fname="${${URL%%\?*}:t}"
command mkdir -p $dir || {
+zi-log "{u-warn}Error{b-warn}:{error} Couldn't create directory:" \
"{dir}$dir{error}, aborting.{rst}"
return 1
}
builtin cd -q $dir || return 1
+zi-log "Downloading tarball for {pid}$plugin{rst}{…}"
if { ! .zinit-download-file-stdout "$URL" 0 1 >! "$fname" } {
if { ! .zinit-download-file-stdout "$URL" 1 1 >! "$fname" } {
command rm -f "$fname"
+zi-log "Download of the file {apo}\`{file}$fname{apo}\`{rst}" \
"failed. No available download tool? One of:" \
"{cmd}${(pj:$tool_sep:)${=:-curl wget lftp lynx}}{rst}."
return 1
}
}
# When extract ice is set, the ∞zinit-extract-hook will handle
# extraction; otherwise extract here with --move as default.
if (( !${+ICE[extract]} )); then
ziextract "$fname" --move
fi
return 0
) && {
reply=( "$user" "$plugin" )
REPLY=tarball
}
} else {
reply=( "${ICE[user]:-$user}" "${ICE[plugin]:-$plugin}" )
if [[ ${ICE[from]} = (|gh-r|github-rel) ]]; then
REPLY=github
else
REPLY=unknown
fi
}
return $?
} # ]]]
# FUNCTION: .zinit-setup-plugin-dir [[[
# Clones given plugin into PLUGIN_DIR. Supports multiple
# sites (respecting `from' and `proto' ice modifiers).
# Invokes compilation of plugin's main file.
#
# $1 - user
# $2 - plugin
.zinit-setup-plugin-dir() {
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt extendedglob warncreateglobal noshortloops rcquotes
local user=$1 plugin=$2 id_as=$3 remote_url_path=${1:+$1/}$2 \
local_path tpe=$4 update=$5 version=$6
if .zinit-get-object-path plugin "$id_as" && [[ -z $update ]] {
+zi-log "{u-warn}ERROR{b-warn}:{error} A plugin named {pid}$id_as{error}" \
"already exists, aborting."
return 1
}
local_path=$REPLY
trap "rmdir ${(qqq)local_path}/._zinit ${(qqq)local_path} 2>/dev/null" EXIT
trap "rmdir ${(qqq)local_path}/._zinit ${(qqq)local_path} 2>/dev/null; return 1" INT TERM QUIT HUP
local -A sites
sites=(
github github.com
gh github.com
bitbucket bitbucket.org
bb bitbucket.org
gitlab gitlab.com
gl gitlab.com
notabug notabug.org
nb notabug.org
github-rel github.com/$remote_url_path/releases
gh-r github.com/$remote_url_path/releases
cygwin cygwin
)
ZINIT[annex-multi-flag:pull-active]=${${${(M)update:#-u}:+${ZINIT[annex-multi-flag:pull-active]}}:-2}
local -a arr
if [[ $user = _local ]]; then
builtin print "Warning: no local plugin \`$plugin\'."
builtin print "(should be located at: $local_path)"
return 1
fi
command rm -f ${TMPDIR:-/tmp}/zinit-execs.$$.lst ${TMPDIR:-/tmp}/zinit.installed_comps.$$.lst \
${TMPDIR:-/tmp}/zinit.skipped_comps.$$.lst ${TMPDIR:-/tmp}/zinit.compiled.$$.lst
if [[ $tpe != tarball ]] {
if [[ -z $update ]] {
.zinit-any-colorify-as-uspl2 "$user" "$plugin"
local pid_hl='{pid}' id_msg_part=" (at label: {id-as}$id_as{rst})"
+zi-log "{nl}{i} Downloading {b}{file}$user${user:+/}$plugin{rst} ${${${id_as:#$user/$plugin}}:+$id_msg_part}{rst}"
}
local site
[[ -n ${ICE[from]} ]] && site=${sites[${ICE[from]}]}
if [[ -z $site && ${ICE[from]} = *(gh-r|github-rel)* ]] {
site=${ICE[from]/(gh-r|github-re)/${sites[gh-r]}}
}
}
(
if [[ $site = */releases ]] {
local tag_version=${ICE[ver]}
if [[ -z $tag_version ]]; then
local url="https://$site/latest"
tag_version="$({.zinit-download-file-stdout $url || .zinit-download-file-stdout $url 1;} 2>/dev/null | command grep -i -m 1 -o 'href=./'$user'/'$plugin'/releases/tag/[^"]\+')"
tag_version=${tag_version##*/}
fi
local url=$site/expanded_assets/$tag_version
.zinit-get-latest-gh-r-url-part "$user" "$plugin" "$url" || return $?
command mkdir -p "$local_path"
[[ -d "$local_path" ]] || return 1
(
.zinit-cd-quiet "$local_path" || return 1
integer count
for REPLY ( $reply ) {
count+=1
url="https://github.com${REPLY}"
if [[ -d $local_path/._zinit ]] {
{ local old_version="$(<$local_path/._zinit/is_release${count:#1})"; } 2>/dev/null
old_version=${old_version/(#b)(\/[^\/]##)(#c4,4)\/([^\/]##)*/${match[2]}}
}
+zi-log "{m} Requesting ${REPLY:t} ${version:+, version $version} ${old_version:+ Current version: $old_version.}{rst}"
if { ! .zinit-download-file-stdout "$url" 0 1 >! "${REPLY:t}" } {
if { ! .zinit-download-file-stdout "$url" 1 1 >! "${REPLY:t}" } {
command rm -f "${REPLY:t}"
+zi-log "Download of release for \`$remote_url_path' " \
"failed.{nl}Tried url: $url."
return 1
}
}
if .zinit-download-file-stdout "$url.sig" 2>/dev/null >! "${REPLY:t}.sig"; then
:
else
command rm -f "${REPLY:t}.sig"
fi
command mkdir -p ._zinit && echo '*' > ._zinit/.gitignore
[[ -d ._zinit ]] || return 2
builtin print -r -- $url >! ._zinit/url || return 3
builtin print -r -- ${REPLY} >! ._zinit/is_release${count:#1} || return 4
# When extract ice is set, the ∞zinit-extract-hook will
# handle extraction; otherwise extract here (no move).
if (( !${+ICE[extract]} )); then
ziextract ${REPLY:t} ${${${#reply}:#1}:+--nobkp}
fi
}
return $?
) || {
return 1
}
} elif [[ $site = cygwin ]] {
command mkdir -p "$local_path/._zinit" && echo '*' > "$local_path/._zinit/.gitignore"
[[ -d "$local_path" ]] || return 1
(
.zinit-cd-quiet "$local_path" || return 1
.zinit-get-cygwin-package "$remote_url_path" || return 1
builtin print -r -- $REPLY >! ._zinit/is_release
ziextract "$REPLY"
) || return $?
} elif [[ $tpe = github ]] {
case ${ICE[proto]} in
(|ftp(|s)|git|http(|s)|rsync|ssh)
:zinit-git-clone() {
local clone_url
if [[ ${ICE[proto]} == "ssh" ]]; then
clone_url="git@${site:-${ICE[from]:-github.com}}:$remote_url_path"
else
clone_url="${ICE[proto]:-https}://${site:-${ICE[from]:-github.com}}/$remote_url_path"
fi
command git clone --progress ${(s: :)ICE[cloneopts]---recursive} \
${(s: :)ICE[depth]:+--depth ${ICE[depth]}} \
"$clone_url" \
"$local_path" \
--config transfer.fsckobjects=false \
--config receive.fsckobjects=false \
--config fetch.fsckobjects=false \
--config pull.rebase=false
integer retval=$?
unfunction :zinit-git-clone
return $retval
}
:zinit-git-clone |& { command ${ZINIT[BIN_DIR]}/share/git-process-output.zsh || cat; }
if (( pipestatus[1] == 141 )) {
:zinit-git-clone
integer retval=$?
if (( retval )) {
builtin print -Pr -- "$ZINIT[col-error]Clone failed (code: $ZINIT[col-obj]$retval$ZINIT[col-error]).%f%b"
return 1
}
} elif (( pipestatus[1] )) {
builtin print -Pr -- "$ZINIT[col-error]Clone failed (code: $ZINIT[col-obj]$pipestatus[1]$ZINIT[col-error]).%f%b"
return 1
}
;;
(*)
builtin print -Pr "${ZINIT[col-error]}Unknown protocol:%f%b ${ICE[proto]}. Expected one of: git, http, https, ssh, ftp, ftps, rsync."
return 1
esac
if [[ -n ${ICE[ver]} ]] {
command git -C "$local_path" checkout "${ICE[ver]}"
}
}
if [[ $update != -u ]] {
hook_rc=0
# Store ices at clone of a plugin
.zinit-store-ices "$local_path/._zinit" ICE "" "" "" ""
reply=(
${(on)ZINIT_EXTS2[(I)zinit hook:\!atclone-pre <->]}
${(on)ZINIT_EXTS[(I)z-annex hook:\!atclone-<-> <->]}
${(on)ZINIT_EXTS2[(I)zinit hook:\!atclone-post <->]}
)
for key in "${reply[@]}"; do
arr=( "${(Q)${(z@)ZINIT_EXTS[$key]:-$ZINIT_EXTS2[$key]}[@]}" )
# Functions calls
"${arr[5]}" plugin "$user" "$plugin" "$id_as" "$local_path" "${${key##(zinit|z-annex) hook:}%% <->}" load
hook_rc=$?
[[ "$hook_rc" -ne 0 ]] && {
# note: this will effectively return the last != 0 rc
retval="$hook_rc"
builtin print -Pr -- "${ZINIT[col-warn]}Warning:%f%b ${ZINIT[col-obj]}${arr[5]}${ZINIT[col-warn]} hook returned with ${ZINIT[col-obj]}${hook_rc}${ZINIT[col-rst]}"
}
done
# Run annexes' atclone hooks (the after atclone-ice ones)
reply=(
${(on)ZINIT_EXTS2[(I)zinit hook:atclone-pre <->]}
${(on)ZINIT_EXTS[(I)z-annex hook:atclone-<-> <->]}
${(on)ZINIT_EXTS2[(I)zinit hook:atclone-post <->]}
)
for key in "${reply[@]}"; do
arr=( "${(Q)${(z@)ZINIT_EXTS[$key]:-$ZINIT_EXTS2[$key]}[@]}" )
"${arr[5]}" plugin "$user" "$plugin" "$id_as" "$local_path" "${${key##(zinit|z-annex) hook:}%% <->}"
hook_rc=$?
[[ "$hook_rc" -ne 0 ]] && {
retval="$hook_rc"
builtin print -Pr -- "${ZINIT[col-warn]}Warning:%f%b ${ZINIT[col-obj]}${arr[5]}${ZINIT[col-warn]} hook returned with ${ZINIT[col-obj]}${hook_rc}${ZINIT[col-rst]}"
}
done
}
return "$retval"
) || return $?
typeset -ga INSTALLED_EXECS
{ INSTALLED_EXECS=( "${(@f)$(<${TMPDIR:-/tmp}/zinit-execs.$$.lst)}" ) } 2>/dev/null
# After additional executions like atclone'' - install completions (1 - plugins)
local -A OPTS
OPTS[opt_-q,--quiet]=1
[[ (0 = ${+ICE[nocompletions]} && ${ICE[as]} != null && ${+ICE[null]} -eq 0) || 0 != ${+ICE[completions]} ]] && \
.zinit-install-completions "$id_as" "" "0"
if [[ -e ${TMPDIR:-/tmp}/zinit.skipped_comps.$$.lst || -e ${TMPDIR:-/tmp}/zinit.installed_comps.$$.lst ]] {
typeset -ga INSTALLED_COMPS SKIPPED_COMPS
{ INSTALLED_COMPS=( "${(@f)$(<${TMPDIR:-/tmp}/zinit.installed_comps.$$.lst)}" ) } 2>/dev/null
{ SKIPPED_COMPS=( "${(@f)$(<${TMPDIR:-/tmp}/zinit.skipped_comps.$$.lst)}" ) } 2>/dev/null
}
if [[ -e ${TMPDIR:-/tmp}/zinit.compiled.$$.lst ]] {
typeset -ga ADD_COMPILED
{ ADD_COMPILED=( "${(@f)$(<${TMPDIR:-/tmp}/zinit.compiled.$$.lst)}" ) } 2>/dev/null
}
# After any download rehash the command table
# This will however miss the as"program" binaries
# as their PATH gets extended - and it is done
# later. It will however work for sbin'' ice.
(( !OPTS[opt_-p,--parallel] )) && rehash
return 0
} # ]]]
# FUNCTION: .zinit-install-completions [[[
# Installs all completions of given plugin. After that they are visible to
# 'compinit'. Visible completions can be selectively disabled and enabled. User
# can access completion data with 'completions' subcommand.
#
# $1 - plugin spec (4 formats: user---plugin, user/plugin, user, plugin)
# $2 - plugin if $1 (i.e., user) given
# $3 - if 1, then reinstall, otherwise only install completions that are not present
.zinit-install-completions() {
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt nullglob extendedglob warncreateglobal typesetsilent noshortloops
local id_as=$1${2:+${${${(M)1:#%}:+$2}:-/$2}}
local reinstall=${3:-0} quiet=${${4:+1}:-0}
(( OPTS[opt_-q,--quiet] )) && quiet=1
[[ $4 = -Q ]] && quiet=2
typeset -ga INSTALLED_COMPS SKIPPED_COMPS
INSTALLED_COMPS=() SKIPPED_COMPS=()
.zinit-any-to-user-plugin "$id_as" ""
local user=${reply[-2]}
local plugin=${reply[-1]}
.zinit-any-colorify-as-uspl2 "$user" "$plugin"
local abbrev_pspec=$REPLY
.zinit-exists-physically-message "$id_as" "" || return 1
# Symlink any completion files included in the plugin directory
typeset -a completions already_symlinked backup_comps
local c cfile bkpfile
# The plugin == . is a semi-hack/trick to handle 'creinstall .' properly
[[ $user == % || ( -z $user && $plugin == . ) ]] && \
completions=( "${plugin}"/**/_[^_.]*~*(*.zwc|*.html|*.txt|*.png|*.jpg|*.jpeg|*.js|*.md|*.yml|*.yaml|*.py|*.ri|_zsh_highlight*|/zsdoc/*|*.ps1)(DN^/) ) || \
completions=( "${ZINIT[PLUGINS_DIR]}/${id_as//\//---}"/**/_[^_.]*~*(*.zwc|*.html|*.txt|*.png|*.jpg|*.jpeg|*.js|*.md|*.yml|*.yaml|*.py|*.ri|_zsh_highlight*|/zsdoc/*|*.ps1)(DN^/) )
already_symlinked=( "${ZINIT[COMPLETIONS_DIR]}"/_[^_.]*~*.zwc(DN) )
backup_comps=( "${ZINIT[COMPLETIONS_DIR]}"/[^_.]*~*.zwc(DN) )
# Symlink completions if they are not already there
# either as completions (_fname) or as backups (fname)
# OR - if its a reinstall
for c in "${completions[@]:A}"; do
cfile="${c:t}"
bkpfile="${cfile#_}"
if [[ ( -z ${already_symlinked[(r)*/$cfile]} || $reinstall = 1 ) &&
-z ${backup_comps[(r)*/$bkpfile]}
]]; then
if [[ $reinstall = 1 ]]; then
# Remove old files
command rm -f "${ZINIT[COMPLETIONS_DIR]}/$cfile" "${ZINIT[COMPLETIONS_DIR]}/$bkpfile"
fi
INSTALLED_COMPS+=( $cfile )
(( quiet )) || builtin print -Pr "Symlinking completion ${ZINIT[col-uname]}$cfile%f%b to completions directory."
command ln -fs "$c" "${ZINIT[COMPLETIONS_DIR]}/$cfile"
# Make compinit notice the change
.zinit-forget-completion "$cfile" "$quiet"
else
SKIPPED_COMPS+=( $cfile )
(( quiet )) || builtin print -Pr "Not symlinking completion \`${ZINIT[col-obj]}$cfile%f%b', it already exists."
(( quiet )) || builtin print -Pr "${ZINIT[col-info2]}Use \`${ZINIT[col-pname]}zinit creinstall $abbrev_pspec${ZINIT[col-info2]}' to force install.%f%b"
fi
done
local comps msg
local -A comp_types=(\$INSTALLED_COMPS 'Installed' \$SKIPPED_COMPS 'Skipped re-installing')
for comps msg in ${(kv)comp_types}; do
local comps_num=${#${(e)comps}}
if (( comps_num > 0 )); then
+zi-log "{m} ${msg} {num}$comps_num{rst} completion${=${comps_num:#1}:+s}"
if (( quiet == 0 )); then
+zi-log "{m} Added $comps_num completion${=${comps_num:#1}:+s} to {var}$comps{rst} array"
fi
fi
done
if (( ZSH_SUBSHELL )) {
builtin print -rl -- $INSTALLED_COMPS >! ${TMPDIR:-/tmp}/zinit.installed_comps.$$.lst
builtin print -rl -- $SKIPPED_COMPS >! ${TMPDIR:-/tmp}/zinit.skipped_comps.$$.lst
}
.zinit-compinit 1 1 &>/dev/null
} # ]]]
# FUNCTION: .zinit-compinit [[[
# User-exposed `compinit' frontend which first ensures that all
# completions managed by Zinit are forgotten by Zshell. After
# that it runs normal `compinit', which should more easily detect
# Zinit's completions.
#
# No arguments.
.zinit-compinit() {
# This might be called during sourcing when setting up the plugins dir, so check that OPTS is actually existing
[[ -n $OPTS && -n ${OPTS[opt_-p,--parallel]} && $1 != 1 ]] && return
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
builtin setopt nullglob extendedglob warncreateglobal typesetsilent
integer use_C=$2
typeset -a symlinked backup_comps
local c cfile bkpfile action
symlinked=( "${ZINIT[COMPLETIONS_DIR]}"/_[^_.]*~*.zwc )
backup_comps=( "${ZINIT[COMPLETIONS_DIR]}"/[^_.]*~*.zwc )
# Delete completions if they are really there, either
# as completions (_fname) or backups (fname)
for c in "${symlinked[@]}" "${backup_comps[@]}"; do
action=0
cfile="${c:t}"
cfile="_${cfile#_}"
bkpfile="${cfile#_}"
#print -Pr "${ZINIT[col-info]}Processing completion $cfile%f%b"
.zinit-forget-completion "$cfile"
done
+zi-log "Initializing completion ({func}compinit{rst}){…}"
command rm -f ${ZINIT[ZCOMPDUMP_PATH]:-${ZDOTDIR:-$HOME}/.zcompdump}
# Workaround for a nasty trick in _vim
(( ${+functions[_vim_files]} )) && unfunction _vim_files
builtin autoload -Uz compinit
compinit ${${(M)use_C:#1}:+-C} -d ${ZINIT[ZCOMPDUMP_PATH]:-${ZDOTDIR:-$HOME}/.zcompdump} "${(Q@)${(z@)ZINIT[COMPINIT_OPTS]}}"
} # ]]]
# FUNCTION: .zinit-download-file-stdout [[[
# Downloads file to stdout. Supports following backend commands:
# curl, wget, lftp, lynx. Used by snippet loading.
.zinit-download-file-stdout() {
local url="$1" restart="$2" progress="${(M)3:#1}"
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt localtraps extendedglob
# Authenticate GitHub API requests when a token is available — the anonymous
# limit of 60 requests/hour/IP is too low for e.g. CI runners. Restricted to
# api.github.com so the token is never sent to any other host.
local -a curl_auth wget_auth
local gh_token=${GITHUB_TOKEN:-$GH_TOKEN}
if [[ $url == https://api.github.com/* && -n $gh_token ]] {
curl_auth=( -H "Authorization: Bearer $gh_token" )
wget_auth=( --header="Authorization: Bearer $gh_token" )
}
# Return file directly for file:// urls, wget doesn't support this schema
if [[ "$url" =~ ^file:// ]] {
local filepath=${url##file://}
<"$filepath"
return "$?"
}
if (( restart )) {
(( ${path[(I)/usr/local/bin]} )) || \
{
path+=( "/usr/local/bin" );
trap "path[-1]=()" EXIT
}
if (( ${+commands[curl]} )); then
if [[ -n $progress ]]; then
command curl --retry 2 --retry-delay 1 "${curl_auth[@]}" --progress-bar -fSL "$url" 2> >(.zinit-single-line >&2) || return 1
else
command curl --retry 2 --retry-delay 1 "${curl_auth[@]}" -fsSL "$url" || return 1
fi
elif (( ${+commands[wget]} )); then
command wget --tries=3 "${wget_auth[@]}" ${${progress:--q}:#1} "$url" -O - || return 1
elif (( ${+commands[lftp]} )); then
command lftp -c "cat $url" || return 1
elif (( ${+commands[lynx]} )); then
command lynx -source "$url" || return 1
else
+zi-log "{u-warn}ERROR{b-warn}:{rst}No download tool detected" \
"(one of: {cmd}curl{rst}, {cmd}wget{rst}, {cmd}lftp{rst}," \
"{cmd}lynx{rst})."
return 2
fi
} else {
if type curl 2>/dev/null 1>&2; then
if [[ -n $progress ]]; then
command curl --retry 2 --retry-delay 1 "${curl_auth[@]}" --progress-bar -fSL "$url" 2> >(.zinit-single-line >&2) || return 1
else
command curl --retry 2 --retry-delay 1 "${curl_auth[@]}" -fsSL "$url" || return 1
fi
elif type wget 2>/dev/null 1>&2; then
command wget --tries=3 "${wget_auth[@]}" ${${progress:--q}:#1} "$url" -O - || return 1
elif type lftp 2>/dev/null 1>&2; then
command lftp -c "cat $url" || return 1
else
.zinit-download-file-stdout "$url" "1" "$progress"
return $?
fi
}
return 0
} # ]]]
# FUNCTION: .zinit-get-url-mtime [[[
# For the given URL returns the date in the Last-Modified
# header as a time stamp
.zinit-get-url-mtime() {
local url="$1" IFS line header
local -a cmd
setopt localoptions localtraps
(( !${path[(I)/usr/local/bin]} )) && \
{
path+=( "/usr/local/bin" );
trap "path[-1]=()" EXIT
}
if (( ${+commands[curl]} )) || type curl 2>/dev/null 1>&2; then
cmd=(command curl -sIL "$url")
elif (( ${+commands[wget]} )) || type wget 2>/dev/null 1>&2; then
cmd=(command wget --server-response --spider -q "$url" -O -)
else
REPLY=$(( $(date +"%s") ))
return 2
fi
"${cmd[@]}" |& command grep -i Last-Modified: | while read -r line; do
header="${${line#*, }//$'\r'}"
done
if [[ -z $header ]] {
REPLY=$(( $(date +"%s") ))
return 3
}
LANG=C TZ=UTC strftime -r -s REPLY "%d %b %Y %H:%M:%S GMT" "$header" &>/dev/null || {
REPLY=$(( $(date +"%s") ))
return 4
}
return 0
} # ]]]
# FUNCTION: .zinit-mirror-using-svn [[[
# Used to clone subdirectories from Github. If in update mode
# (see $2), then invokes `svn update', in normal mode invokes
# `svn checkout --non-interactive -q <URL>'. In test mode only
# compares remote and local revision and outputs true if update
# is needed.
#
# $1 - URL
# $2 - mode, "" - normal, "-u" - update, "-t" - test
# $3 - subdirectory (not path) with working copy, needed for -t and -u
.zinit-mirror-using-svn() {
setopt localoptions extendedglob warncreateglobal
local url="$1" update="$2" directory="$3"
(( ${+commands[svn]} )) || \
builtin print -Pr -- "${ZINIT[col-error]}Warning:%f%b Subversion not found" \
", please install it to use \`${ZINIT[col-obj]}svn%f%b' ice."
if [[ "$update" = "-t" ]]; then
(
.zinit-cd-quiet "$directory"
local -a out1 out2
out1=( "${(f@)"$(LANG=C svn info -r HEAD)"}" )
out2=( "${(f@)"$(LANG=C svn info)"}" )
out1=( "${(M)out1[@]:#Revision:*}" )
out2=( "${(M)out2[@]:#Revision:*}" )
[[ "${out1[1]##[^0-9]##}" != "${out2[1]##[^0-9]##}" ]] && return 0
return 1
)
return $?
fi
if [[ "$update" = "-u" && -d "$directory" && -d "$directory/.svn" ]]; then
( .zinit-cd-quiet "$directory"
command svn update
return $? )
else
command svn checkout --non-interactive -q "$url" "$directory"
fi
return $?
} # ]]]
# FUNCTION: .zinit-forget-completion [[[
# Implements alternation of Zsh state so that already initialized
# completion stops being visible to Zsh.
#
# $1 - completion function name, e.g. "_cp"; can also be "cp"
.zinit-forget-completion() {
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt extendedglob typesetsilent warncreateglobal
local f="$1" quiet="$2"
typeset -a commands
commands=( ${(k)_comps[(Re)$f]} )
[[ "${#commands}" -gt 0 ]] && (( quiet == 0 )) && builtin print -Prn "Forgetting commands completed by \`${ZINIT[col-obj]}$f%f%b': "
local k
integer first=1
for k ( $commands ) {
unset "_comps[$k]"
(( quiet )) || builtin print -Prn "${${first:#1}:+, }${ZINIT[col-info]}$k%f%b"
first=0
}
(( quiet || first )) || builtin print
unfunction -- 2>/dev/null "$f"
} # ]]]
# FUNCTION: .zinit-download-snippet [[[
# Downloads snippet
# file with curl, wget, lftp or lynx,
# directory, with Subversion when svn-ICE is active.
#
# Github supports Subversion protocol and allows to clone subdirectories.
# This is used to provide a layer of support for Oh-My-Zsh and Prezto.
.zinit-download-snippet() {
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt extendedglob warncreateglobal typesetsilent
local save_url=$1 url=$2 id_as=$3 local_dir=$4 dirname=$5 filename=$6 update=$7
trap "command rmdir ${(qqq)local_dir}/${(qqq)dirname} 2>/dev/null; return 1;" INT TERM QUIT HUP
local -a list arr
integer retval=0 hook_rc=0
local teleid_clean=${ICE[teleid]%%\?*}
[[ $teleid_clean == *://* ]] && \
local sname=${(M)teleid_clean##*://[^/]##(/[^/]##)(#c0,4)} || \
local sname=${${teleid_clean:h}:t}/${teleid_clean:t}
[[ $sname = */trunk* ]] && sname=${${ICE[teleid]%%/trunk*}:t}/${ICE[teleid]:t}
sname=${sname#./}
if (( ${+ICE[svn]} )) {
[[ $url = *(${(~kj.|.)${(Mk)ZINIT_1MAP:#OMZ*}}|robbyrussell*oh-my-zsh|ohmyzsh/ohmyzsh)* ]] && local ZSH=${ZINIT[SNIPPETS_DIR]}
url=${url/(#s)(#m)(${(~kj.|.)ZINIT_1MAP})/$ZINIT_1MAP[$MATCH]}
} else {
url=${url/(#s)(#m)(${(~kj.|.)ZINIT_2MAP})/$ZINIT_2MAP[$MATCH]}
if [[ $save_url == (${(~kj.|.)${(Mk)ZINIT_1MAP:#OMZ*}})* ]] {
if [[ $url != *.zsh(|-theme) && $url != */_[^/]## ]] {
if [[ $save_url == OMZT::* ]] {
url+=.zsh-theme
} else {
url+=/${${url#*::}:t}.plugin.zsh
}
}
} elif [[ $save_url = (${(~kj.|.)${(kM)ZINIT_1MAP:#PZT*}})* ]] {
if [[ $url != *.zsh && $url != */_[^/]## ]] {
url+=/init.zsh
}
}
}
# Change the url to point to raw github content if it isn't like that
if [[ "$url" = *github.com* && ! "$url" = */raw/* && "${+ICE[svn]}" = "0" ]] {
url="${${url/\/blob\///raw/}/\/tree\///raw/}"
}
command rm -f ${TMPDIR:-/tmp}/zinit-execs.$$.lst ${TMPDIR:-/tmp}/zinit.installed_comps.$$.lst \
${TMPDIR:-/tmp}/zinit.skipped_comps.$$.lst ${TMPDIR:-/tmp}/zinit.compiled.$$.lst
if [[ ! -d $local_dir/$dirname ]]; then
local id_msg_part="{…} (at label{ehi}:{rst} {id-as}$id_as{rst})"
[[ $update != -u ]] && +zi-log "{nl}{info}Setting up snippet:" \
"{url}$sname{rst}${ICE[id-as]:+$id_msg_part}"
command mkdir -p "$local_dir"
fi
if [[ $update = -u && ${OPTS[opt_-q,--quiet]} != 1 ]]; then
local id_msg_part="{…} (identified as{ehi}:{rst} {id-as}$id_as{rst})"
+zi-log "{nl}{info2}Updating snippet: {url}$sname{rst}${ICE[id-as]:+$id_msg_part}"
fi
# A flag for the annexes. 0 no new commits, 1 - run-atpull mode,
# 2 full update/there are new commits to download, 3 - full but
# a forced download (i.e.: the medium doesn't allow to peek update)
#
# The below inherits the flag if it's an update call (i.e.: -u given),
# otherwise it sets it to 2 a new download is treated like a full
# update.
ZINIT[annex-multi-flag:pull-active]=${${${(M)update:#-u}:+${ZINIT[annex-multi-flag:pull-active]}}:-2}
(
if [[ $url = (ftp(|s)|http(|s)|scp)://* ]] {
(
.zinit-cd-quiet "$local_dir" || return 4
(( !OPTS[opt_-q,--quiet] )) && +zi-log "{i} Downloading {file}$sname{rst} ${${ICE[svn]+" (with Subversion)"}:-" (with curl, wget, lftp)"}{rst}"
if (( ${+ICE[svn]} )) {
if [[ $update = -u ]] {
# Test if update available
if ! .zinit-mirror-using-svn "$url" "-t" "$dirname"; then
if (( ${+ICE[run-atpull]} || OPTS[opt_-u,--urge] )) {
ZINIT[annex-multi-flag:pull-active]=1
} else { return 0; } # Will return when no updates so atpull''
# code below doesn't need any checks.
# This return 0 statement also sets the
# pull-active flag outside this subshell.
else
ZINIT[annex-multi-flag:pull-active]=2
fi
# Run annexes' atpull hooks (the before atpull-ice ones).
# The SVN block.
reply=(
${(on)ZINIT_EXTS2[(I)zinit hook:e-\!atpull-pre <->]}
${${(M)ICE[atpull]#\!}:+${(on)ZINIT_EXTS[(I)z-annex hook:\!atpull-<-> <->]}}
${(on)ZINIT_EXTS2[(I)zinit hook:e-\!atpull-post <->]}
)
for key in "${reply[@]}"; do
arr=( "${(Q)${(z@)ZINIT_EXTS[$key]:-$ZINIT_EXTS2[$key]}[@]}" )
"${arr[5]}" snippet "$save_url" "$id_as" "$local_dir/$dirname" "${${key##(zinit|z-annex) hook:}%% <->}" update:svn
hook_rc=$?
[[ "$hook_rc" -ne 0 ]] && {
retval="$hook_rc"
builtin print -Pr -- "${ZINIT[col-warn]}Warning:%f%b ${ZINIT[col-obj]}${arr[5]}${ZINIT[col-warn]} hook returned with ${ZINIT[col-obj]}${hook_rc}${ZINIT[col-rst]}"
}
done
if (( ZINIT[annex-multi-flag:pull-active] == 2 )) {
# Do the update
# The condition is reversed on purpose to show only
# the messages on an actual update
if (( OPTS[opt_-q,--quiet] )); then
local id_msg_part="{…} (identified as{ehi}: {id-as}$id_as{rst})"
+zi-log "{nl}{info2}Updating snippet {url}${sname}{rst}${ICE[id-as]:+$id_msg_part}"
+zi-log "Downloading {apo}\`{rst}$sname{apo}\`{rst} (with Subversion){…}"
fi
.zinit-mirror-using-svn "$url" "-u" "$dirname" || return 4
}
} else {
.zinit-mirror-using-svn "$url" "" "$dirname" || return 4
}
# Redundant code, just to compile SVN snippet
if [[ ${ICE[as]} != command ]]; then
if [[ -n ${ICE[pick]} ]]; then
list=( ${(M)~ICE[pick]##/*}(DN) $local_dir/$dirname/${~ICE[pick]}(DN) )
elif [[ -z ${ICE[pick]} ]]; then
list=(
$local_dir/$dirname/*.plugin.zsh(DN) $local_dir/$dirname/*.zsh-theme(DN) $local_dir/$dirname/init.zsh(DN)
$local_dir/$dirname/*.zsh(DN) $local_dir/$dirname/*.sh(DN) $local_dir/$dirname/.zshrc(DN)
)
fi
if [[ -e ${list[1]} && ${list[1]} != */dev/null && \
-z ${ICE[(i)(\!|)(sh|bash|ksh|csh)]} && \
${+ICE[nocompile]} -eq 0
]] {
() {
builtin emulate -LR zsh -o extendedglob ${=${options[xtrace]:#off}:+-o xtrace}
zcompile -U "${list[1]}" &>/dev/null || \
+zi-log "{u-warn}Warning{b-warn}:{rst} couldn't compile {apo}\`{file}${list[1]}{apo}\`{rst}."
}
}
fi
return $ZINIT[annex-multi-flag:pull-active]
} else {
command mkdir -p "$local_dir/$dirname"
if (( !OPTS[opt_-f,--force] )) {
.zinit-get-url-mtime "$url"
} else {
REPLY=$EPOCHSECONDS
}
# Returned is: modification time of the remote file.
# Thus, EPOCHSECONDS - REPLY is: allowed window for the
# local file to be modified in. ms-$secs is: files accessed
# within last $secs seconds. Thus, if there's no match, the
# local file is out of date.
local secs=$(( EPOCHSECONDS - REPLY ))
# Guard so that it's positive
(( $secs >= 0 )) || secs=0
integer skip_dl
local -a matched
matched=( $local_dir/$dirname/$filename(DNms-$secs) )
if (( ${#matched} )) {
+zi-log "{info}Already up to date.{rst}"
# Empty-update return-short path it also decides the
# pull-active flag after the return from this sub-shell
(( ${+ICE[run-atpull]} || OPTS[opt_-u,--urge] )) && skip_dl=1 || return 0
}
if [[ ! -f $local_dir/$dirname/$filename ]] {
ZINIT[annex-multi-flag:pull-active]=2
} else {
# secs > 1 → the file is outdated, then:
# - if true, then the mode is 2 minus run-atpull-activation,
# - if false, then mode is 3 → a forced download (no remote mtime found).
ZINIT[annex-multi-flag:pull-active]=$(( secs > 1 ? (2 - skip_dl) : 3 ))
}
# Run annexes' atpull hooks (the before atpull-ice ones).
# The URL-snippet block.
if [[ $update = -u && $ZINIT[annex-multi-flag:pull-active] -ge 1 ]] {
reply=(
${(on)ZINIT_EXTS2[(I)zinit hook:e-\!atpull-pre <->]}
${${ICE[atpull]#\!}:+${(on)ZINIT_EXTS[(I)z-annex hook:\!atpull-<-> <->]}}
${(on)ZINIT_EXTS2[(I)zinit hook:e-\!atpull-post <->]}
)
for key in "${reply[@]}"; do
arr=( "${(Q)${(z@)ZINIT_EXTS[$key]:-$ZINIT_EXTS2[$key]}[@]}" )
"${arr[5]}" snippet "$save_url" "$id_as" "$local_dir/$dirname" "${${key##(zinit|z-annex) hook:}%% <->}" update:url
hook_rc="$?"
[[ "$hook_rc" -ne 0 ]] && {
retval="$hook_rc"
builtin print -Pr -- "${ZINIT[col-warn]}Warning:%f%b ${ZINIT[col-obj]}${arr[5]}${ZINIT[col-warn]} hook returned with ${ZINIT[col-obj]}${hook_rc}${ZINIT[col-rst]}"
}
done
}
if (( !skip_dl )) {
if { ! .zinit-download-file-stdout "$url" 0 1 >! "$dirname/$filename" } {
if { ! .zinit-download-file-stdout "$url" 1 1 >! "$dirname/$filename" } {
command rm -f "$dirname/$filename"
+zi-log "{u-warn}ERROR{b-warn}:{rst} Download failed."
return 4
}
}
}
return $ZINIT[annex-multi-flag:pull-active]
}
)
retval=$?
# Overestimate the pull-level to 2 also in error situations
# no hooks will be run anyway because of the error
ZINIT[annex-multi-flag:pull-active]=$retval
if [[ $ICE[as] != command && ${+ICE[svn]} -eq 0 ]] {
local file_path=$local_dir/$dirname/$filename
if [[ -n ${ICE[pick]} ]]; then
list=( ${(M)~ICE[pick]##/*}(DN) $local_dir/$dirname/${~ICE[pick]}(DN) )
file_path=${list[1]}
fi
if [[ -e $file_path && -z ${ICE[(i)(\!|)(sh|bash|ksh|csh)]} && \
$file_path != */dev/null && ${+ICE[nocompile]} -eq 0
]] {
() {
builtin emulate -LR zsh -o extendedglob ${=${options[xtrace]:#off}:+-o xtrace}
if ! zcompile -U "$file_path" 2>/dev/null; then
builtin print -r "Couldn't compile \`${file_path:t}', it MIGHT be wrongly downloaded"
builtin print -r "(snippet URL points to a directory instead of a file?"
builtin print -r "to download directory, use preceding: zinit ice svn)."
retval=4
fi
}
}
}
} else { # Local-file snippet branch
# Local files are (yet…) forcefully copied.
ZINIT[annex-multi-flag:pull-active]=3 retval=3
# Run annexes' atpull hooks (the before atpull-ice ones).
# The local-file snippets block.
if [[ $update = -u ]] {
reply=(
${(on)ZINIT_EXTS2[(I)zinit hook:e-\!atpull-pre <->]}
${${(M)ICE[atpull]#\!}:+${(on)ZINIT_EXTS[(I)z-annex hook:\!atpull-<-> <->]}}
${(on)ZINIT_EXTS2[(I)zinit hook:e-\!atpull-post <->]}
)
for key in "${reply[@]}"; do
arr=( "${(Q)${(z@)ZINIT_EXTS[$key]:-$ZINIT_EXTS2[$key]}[@]}" )
"${arr[5]}" snippet "$save_url" "$id_as" "$local_dir/$dirname" "${${key##(zinit|z-annex) hook:}%% <->}" update:file
hook_rc="$?"
[[ "$hook_rc" -ne 0 ]] && {
retval="$hook_rc"
builtin print -Pr -- "${ZINIT[col-warn]}Warning:%f%b ${ZINIT[col-obj]}${arr[5]}${ZINIT[col-warn]} hook returned with ${ZINIT[col-obj]}${hook_rc}${ZINIT[col-rst]}"
}
done
}
command mkdir -p "$local_dir/$dirname"
if [[ ! -e $url ]] {
(( !OPTS[opt_-q,--quiet] )) && +zi-log "{ehi}ERROR:{error} The source file {file}$url{error} doesn't exist.{rst}"
retval=4
}
if [[ -e $url && ! -f $url && $url != /dev/null ]] {
(( !OPTS[opt_-q,--quiet] )) && +zi-log "{ehi}ERROR:{error} The source {file}$url{error} isn't a regular file.{rst}"
retval=4
}
if [[ -e $url && ! -r $url && $url != /dev/null ]] {
(( !OPTS[opt_-q,--quiet] )) && +zi-log "{ehi}ERROR:{error} The source {file}$url{error} isn't" \
"accessible (wrong permissions).{rst}"
retval=4
}
if ! (( ${+ICE[link]} )) {
if (( !OPTS[opt_-q,--quiet] )) && [[ $url != /dev/null ]] {
+zi-log "{msg}Copying {file}$filename{msg}{…}{rst}"
command cp -vf "$url" "$local_dir/$dirname/$filename" || \
{ +zi-log "{ehi}ERROR:{error} The file copying has been unsuccessful.{rst}"; retval=4; }
} else {
command cp -f "$url" "$local_dir/$dirname/$filename" &>/dev/null || \
{ +zi-log "{ehi}ERROR:{error} The copying of {file}$filename{error} has been unsuccessful"\
"${${(M)OPTS[opt_-q,--quiet]:#1}:+, skip the -q/--quiet option for more information}.{rst}"; retval=4; }
}
} else {
if (( $+commands[realpath] )) {
local rpv="$(realpath --version | head -n1 | sed -E 's/realpath (\(.*\))?//g')"
if is-at-least 8.23 $rpv; then
rel_url="$(realpath --relative-to="$local_dir/$dirname" "$url")" && \
{ url="$rel_url" }
fi
}
if (( !OPTS[opt_-q,--quiet] )) && [[ $url != /dev/null ]] {
+zi-log "{msg}Linking {file}$filename{msg}{…}{rst}"
command ln -svf "$url" "$local_dir/$dirname/$filename" || \
{ +zi-log "{ehi}ERROR:{error} The file linking has been unsuccessful.{rst}"; retval=4; }
} else {
command ln -sf "$url" "$local_dir/$dirname/$filename" &>/dev/null || \
{ +zi-log "{ehi}ERROR:{error} The link of {file}$filename{error} has been unsuccessful"\
"${${(M)OPTS[opt_-q,--quiet]:#1}:+, skip the -q/--quiet option for more information}.{rst}"; retval=4; }
}
}
}
(( retval == 4 )) && { command rmdir "$local_dir/$dirname" 2>/dev/null; return $retval; }
if [[ ${${:-$local_dir/$dirname}%%/##} != ${ZINIT[SNIPPETS_DIR]} ]] {
# Store ices at "clone" and update of snippet, SVN and single-file
local pfx=$local_dir/$dirname/._zinit
.zinit-store-ices "$pfx" ICE url_rsvd "" "$save_url" "${+ICE[svn]}"
} elif [[ -n $id_as ]] {
+zi-log "{u-warn}Warning{b-warn}:{rst} the snippet {url}$id_as{rst} isn't" \
"fully downloaded you should remove it with {apo}\`{cmd}zinit delete $id_as{apo}\`{rst}."
}
# Empty update short-path
if (( ZINIT[annex-multi-flag:pull-active] == 0 )) {
# Run annexes' atpull hooks (the `always' after atpull-ice ones)
reply=(
${(on)ZINIT_EXTS2[(I)zinit hook:%atpull-pre <->]}
${(on)ZINIT_EXTS[(I)z-annex hook:%atpull-<-> <->]}
${(on)ZINIT_EXTS2[(I)zinit hook:%atpull-post <->]}
)
for key in "${reply[@]}"; do
arr=( "${(Q)${(z@)ZINIT_EXTS[$key]:-$ZINIT_EXTS2[$key]}[@]}" )
"${arr[5]}" snippet "$save_url" "$id_as" "$local_dir/$dirname" "${${key##(zinit|z-annex) hook:}%% <->}" update:0
hook_rc="$?"
[[ "$hook_rc" -ne 0 ]] && {
retval="$hook_rc"
builtin print -Pr -- "${ZINIT[col-warn]}Warning:%f%b ${ZINIT[col-obj]}${arr[5]}${ZINIT[col-warn]} hook returned with ${ZINIT[col-obj]}${hook_rc}${ZINIT[col-rst]}"
}
done
return $retval;
}
if [[ $update = -u ]] {
# Run annexes' atpull hooks (the before atpull-ice ones).
# The block is common to all 3 snippet types.
reply=(
${(on)ZINIT_EXTS2[(I)zinit hook:no-e-\!atpull-pre <->]}
${${ICE[atpull]:#\!*}:+${(on)ZINIT_EXTS[(I)z-annex hook:\!atpull-<-> <->]}}
${(on)ZINIT_EXTS2[(I)zinit hook:no-e-\!atpull-post <->]}
)
for key in "${reply[@]}"; do
arr=( "${(Q)${(z@)ZINIT_EXTS[$key]:-$ZINIT_EXTS2[$key]}[@]}" )
"${arr[5]}" snippet "$save_url" "$id_as" "$local_dir/$dirname" "${${key##(zinit|z-annex) hook:}%% <->}" update
hook_rc=$?
[[ "$hook_rc" -ne 0 ]] && {
retval="$hook_rc"
builtin print -Pr -- "${ZINIT[col-warn]}Warning:%f%b ${ZINIT[col-obj]}${arr[5]}${ZINIT[col-warn]} hook returned with ${ZINIT[col-obj]}${hook_rc}${ZINIT[col-rst]}"
}
done
} else {
# Run annexes' atclone hooks (the before atclone-ice ones)
# The block is common to all 3 snippet types.
reply=(
${(on)ZINIT_EXTS2[(I)zinit hook:\!atclone-pre <->]}
${(on)ZINIT_EXTS[(I)z-annex hook:\!atclone-<-> <->]}
${(on)ZINIT_EXTS2[(I)zinit hook:\!atclone-post <->]}
)
for key in "${reply[@]}"; do
arr=( "${(Q)${(z@)ZINIT_EXTS[$key]:-$ZINIT_EXTS2[$key]}[@]}" )
"${arr[5]}" snippet "$save_url" "$id_as" "$local_dir/$dirname" "${${key##(zinit|z-annex) hook:}%% <->}" load
done
reply=(
${(on)ZINIT_EXTS2[(I)zinit hook:atclone-pre <->]}
${(on)ZINIT_EXTS[(I)z-annex hook:atclone-<-> <->]}
${(on)ZINIT_EXTS2[(I)zinit hook:atclone-post <->]}
)
for key in "${reply[@]}"; do
arr=( "${(Q)${(z@)ZINIT_EXTS[$key]:-$ZINIT_EXTS2[$key]}[@]}" )
"${arr[5]}" snippet "$save_url" "$id_as" "$local_dir/$dirname" "${${key##(zinit|z-annex) hook:}%% <->}" load
done
}
# Run annexes' atpull hooks (the after atpull-ice ones)
# The block is common to all 3 snippet types.
if [[ $update = -u ]] {
if (( ZINIT[annex-multi-flag:pull-active] > 0 )) {
reply=(
${(on)ZINIT_EXTS2[(I)zinit hook:atpull-pre <->]}
${(on)ZINIT_EXTS[(I)z-annex hook:atpull-<-> <->]}
${(on)ZINIT_EXTS2[(I)zinit hook:atpull-post <->]}
)
for key in "${reply[@]}"; do
arr=( "${(Q)${(z@)ZINIT_EXTS[$key]:-$ZINIT_EXTS2[$key]}[@]}" )
"${arr[5]}" snippet "$save_url" "$id_as" "$local_dir/$dirname" "${${key##(zinit|z-annex) hook:}%% <->}" update
hook_rc=$?
[[ "$hook_rc" -ne 0 ]] && {
retval="$hook_rc"
builtin print -Pr -- "${ZINIT[col-warn]}Warning:%f%b ${ZINIT[col-obj]}${arr[5]}${ZINIT[col-warn]} hook returned with ${ZINIT[col-obj]}${hook_rc}${ZINIT[col-rst]}"
}
done
}
# Run annexes' atpull hooks (the `always' after atpull-ice ones)
# The block is common to all 3 snippet types.
reply=(
${(on)ZINIT_EXTS2[(I)zinit hook:%atpull-pre <->]}
${(on)ZINIT_EXTS[(I)z-annex hook:%atpull-<-> <->]}
${(on)ZINIT_EXTS2[(I)zinit hook:%atpull-post <->]}
)
for key in "${reply[@]}"; do
arr=( "${(Q)${(z@)ZINIT_EXTS[$key]:-$ZINIT_EXTS2[$key]}[@]}" )
"${arr[5]}" snippet "$save_url" "$id_as" "$local_dir/$dirname" "${${key##(zinit|z-annex) hook:}%% <->}" update:$ZINIT[annex-multi-flag:pull-active]
hook_rc=$?
[[ "$hook_rc" -ne 0 ]] && {
retval="$hook_rc"
builtin print -Pr -- "${ZINIT[col-warn]}Warning:%f%b ${ZINIT[col-obj]}${arr[5]}${ZINIT[col-warn]} hook returned with ${ZINIT[col-obj]}${hook_rc}${ZINIT[col-rst]}"
}
done
}
) || return $?
typeset -ga INSTALLED_EXECS
{ INSTALLED_EXECS=( "${(@f)$(<${TMPDIR:-/tmp}/zinit-execs.$$.lst)}" ) } 2>/dev/null
# After additional executions like atclone'' - install completions (2 - snippets)
local -A OPTS
OPTS[opt_-q,--quiet]=1
[[ (0 = ${+ICE[nocompletions]} && ${ICE[as]} != null && ${+ICE[null]} -eq 0) || 0 != ${+ICE[completions]} ]] && \
.zinit-install-completions "%" "$local_dir/$dirname" 0
if [[ -e ${TMPDIR:-/tmp}/zinit.skipped_comps.$$.lst || -e ${TMPDIR:-/tmp}/zinit.installed_comps.$$.lst ]] {
typeset -ga INSTALLED_COMPS SKIPPED_COMPS
{ INSTALLED_COMPS=( "${(@f)$(<${TMPDIR:-/tmp}/zinit.installed_comps.$$.lst)}" ) } 2>/dev/null
{ SKIPPED_COMPS=( "${(@f)$(<${TMPDIR:-/tmp}/zinit.skipped_comps.$$.lst)}" ) } 2>/dev/null
}
if [[ -e ${TMPDIR:-/tmp}/zinit.compiled.$$.lst ]] {
typeset -ga ADD_COMPILED
{ ADD_COMPILED=( "${(@f)$(<${TMPDIR:-/tmp}/zinit.compiled.$$.lst)}" ) } 2>/dev/null
}
# After any download rehash the command table
# This will however miss the as"program" binaries
# as their PATH gets extended - and it is done
# later. It will however work for sbin'' ice.
(( !OPTS[opt_-p,--parallel] )) && rehash
return $retval
} # ]]]
# FUNCTION: .zinit-update-snippet [[[
.zinit-update-snippet() {
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt extendedglob warncreateglobal typesetsilent noshortloops rcquotes
local -a tmp opts
local url=$1
integer correct=0
[[ -o ksharrays ]] && correct=1
opts=( -u ) # for zinit-annex-readurl
# Create a local copy of OPTS, basically
# for zinit-annex-readurl annex
local -A ice_opts
ice_opts=( "${(kv)OPTS[@]}" )
local -A OPTS
OPTS=( "${(kv)ice_opts[@]}" )
ZINIT[annex-multi-flag:pull-active]=0 ZINIT[-r/--reset-opt-hook-has-been-run]=0
# Remove leading whitespace and trailing /
url=${${url#${url%%[! $'\t']*}}%/}
ICE[teleid]=${ICE[teleid]:-$url}
[[ ${ICE[as]} = null || ${+ICE[null]} -eq 1 || ${+ICE[binary]} -eq 1 ]] && \
ICE[pick]=${ICE[pick]:-/dev/null}
local local_dir dirname filename save_url=$url \
id_as=${ICE[id-as]:-$url}
.zinit-pack-ice "$id_as" ""
# Allow things like $OSTYPE in the URL
eval "url=\"$url\""
# - case A: called from `update --all', ICE empty, static ice will win
# - case B: called from `update', ICE packed, so it will win
tmp=( "${(Q@)${(z@)ZINIT_SICE[$id_as]}}" )
if (( ${#tmp} > 1 && ${#tmp} % 2 == 0 )) {
ICE=( "${(kv)ICE[@]}" "${tmp[@]}" )
} elif [[ -n ${ZINIT_SICE[$id_as]} ]] {
+zi-log "{error}WARNING:{msg2} Inconsistency #3" \
"occurred, please report the string: \`{obj}${ZINIT_SICE[$id_as]}{msg2}' to the" \
"GitHub issues page: {obj}https://github.com/zdharma-continuum/zinit/issues/{msg2}.{rst}"
}
id_as=${ICE[id-as]:-$id_as}
# Oh-My-Zsh, Prezto and manual shorthands
if (( ${+ICE[svn]} )) {
[[ $url = *(${(~kj.|.)${(Mk)ZINIT_1MAP:#OMZ*}}|robbyrussell*oh-my-zsh|ohmyzsh/ohmyzsh)* ]] && local ZSH=${ZINIT[SNIPPETS_DIR]}
url=${url/(#s)(#m)(${(~kj.|.)ZINIT_1MAP})/$ZINIT_1MAP[$MATCH]}
} else {
url=${url/(#s)(#m)(${(~kj.|.)ZINIT_2MAP})/$ZINIT_2MAP[$MATCH]}
if [[ $save_url == (${(~kj.|.)${(Mk)ZINIT_1MAP:#OMZ*}})* ]] {
if [[ $url != *.zsh(|-theme) && $url != */_[^/]## ]] {
if [[ $save_url == OMZT::* ]] {
url+=.zsh-theme
} else {
url+=/${${url#*::}:t}.plugin.zsh
}
}
} elif [[ $save_url = (${(~kj.|.)${(kM)ZINIT_1MAP:#PZT*}})* ]] {
if [[ $url != *.zsh ]] {
url+=/init.zsh
}
}
}
if { ! .zinit-get-object-path snippet "$id_as" } {
+zi-log "{msg2}Error: the snippet \`{obj}$id_as{msg2}'" \
"doesn't exist, aborting the update.{rst}"
return 1
}
filename=$reply[-2] dirname=$reply[-2] local_dir=$reply[-3]
local -a arr
local key
reply=(
${(on)ZINIT_EXTS2[(I)zinit hook:preinit-pre <->]}
${(on)ZINIT_EXTS[(I)z-annex hook:preinit-<-> <->]}
${(on)ZINIT_EXTS2[(I)zinit hook:preinit-post <->]}
)
for key in "${reply[@]}"; do
arr=( "${(Q)${(z@)ZINIT_EXTS[$key]:-$ZINIT_EXTS2[$key]}[@]}" )
"${arr[5]}" snippet "$save_url" "$id_as" "$local_dir/$dirname" ${${key##(zinit|z-annex) hook:}%% <->} update || \
return $(( 10 - $? ))
done
# Download or copy the file
[[ $url = *github.com* && $url != */raw/* ]] && url=${url/\/(blob|tree)\///raw/}
.zinit-download-snippet "$save_url" "$url" "$id_as" "$local_dir" "$dirname" "$filename" "-u"
return $?
} # ]]]
# FUNCTION: .zinit-single-line [[[
# Display cURL progress bar on a single line
.zinit-single-line() {
emulate -LR zsh
setopt extendedglob noshortloops nowarncreateglobal rcquotes typesetsilent
local IFS= n=$'\n' r=$'\r' zero=$'\0'
{
command perl -pe 'BEGIN { $|++; $/ = \1 }; tr/\r\n/\n\0/' \
|| gstdbuf -o0 gtr '\r\n' '\n\0' \
|| stdbuf -o0 tr '\r\n' '\n\0';
print
} 2>/dev/null | while read -r line;
do
if [[ $line == *$zero* ]]; then
# cURL doesn't add a newline to progress bars
# print -nr -- "${r}${(l:COLUMNS:: :):-}${r}${line##*${zero}}"
print -nr -- "${r}${(l:COLUMNS:: :):-}${r}${line%${zero}}"
else
print -nr -- "${r}${(l:COLUMNS:: :):-}${r}${${line//[${r}${n}]/}%\%*}${${(M)line%\%}:+%}"
fi
done
print
} # ]]]
# FUNCTION: .zi::get-architecture [[[
.zi::get-architecture () {
emulate -L zsh
setopt extendedglob noshortloops nowarncreateglobal rcquotes
local _clib="gnu" _cpu="$(uname -m)" _os="$(uname -s)" _sys=""
case "$_os" in
(Darwin)
_sys='(apple|darwin|apple-darwin|dmg|mac((-|)os|)|os(-|64|)x)'
arch -x86_64 /usr/bin/true 2> /dev/null
if [[ $? -eq 0 ]] && [[ $_cpu != "arm64" ]]; then
_os=$_sys*~*((aarch|arm)64)
fi
;;
(Linux)
_sys='(musl|gnu)*~^*(unknown|)linux*'
;;
(MINGW* | MSYS* | CYGWIN* | Windows_NT)
_sys='pc-windows-gnu'
;;
(*)
+zi-log "{e} {b}gh-r{rst}Unsupported OS: {obj}$_os{rst}"
;;
esac
case "$_cpu" in
(aarch64 | arm64)
_cpu='(arm|aarch)64'
;;
(amd64 | i386 | i486 | i686| i786 | x64 | x86 | x86-64 | x86_64)
_cpu='(amd64|x86_64|x64)'
;;
(armv6l)
_os=${_os}eabihf
;;
(armv7l | armv8l)
_os=${_os}eabihf
;;
(*)
+zi-log "{e} {b}gh-r{rst}Unsupported CPU: {obj}$_cpu{rst}"
;;
esac
echo "${_sys};${_cpu};${_os}"
} # ]]]
# FUNCTION: .zinit-get-latest-gh-r-url-part [[[
# Gets version string of latest release of given Github
# package. Connects to Github releases page.
.zinit-get-latest-gh-r-url-part () {
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt extendedglob nowarncreateglobal typesetsilent noshortloops
REPLY=
local plugin="$2" urlpart="$3" user="$1"
local -a bpicks filtered init_list list parts
parts=(${(@s:;:)$(.zi::get-architecture)})
if [[ -z $urlpart ]]; then
local tag_version=${ICE[ver]}
if [[ -z $tag_version ]]; then
# Try GitHub API first, fallback to HTML parsing
local api_url=https://api.github.com/repos/$user/$plugin/releases/latest
tag_version="$( { .zinit-download-file-stdout $api_url || .zinit-download-file-stdout $api_url 1; } 2>/dev/null | command grep -o '"tag_name"[[:space:]]*:[[:space:]]*"[^"]\+"' | command grep -o '"[^"]*"$' | tr -d '"' )"
# Fallback to original method if API fails
if [[ -z $tag_version ]]; then
local releases_url=https://github.com/$user/$plugin/releases/latest
tag_version="$( { .zinit-download-file-stdout $releases_url || .zinit-download-file-stdout $releases_url 1; } 2>/dev/null | command grep -m1 -o 'href=./'$user'/'$plugin'/releases/tag/[^"]\+' )"
fi
tag_version=${tag_version##*/}
fi
local url=https://github.com/$user/$plugin/releases/expanded_assets/$tag_version
else
local url=https://$urlpart
fi
if [[ "${ICE[bpick]}" == "src" ]]; then
+zi-log "{dbg} {b}gh-r{rst}: bpick\"src\" detected, targeting source code tarball for tag: {version}$tag_version{rst}"
# Construct the URL path for the auto-generated source code archive
reply=( "/$user/$plugin/archive/refs/tags/$tag_version.tar.gz" )
# Ensure the reply isn't empty if tag_version was somehow missed
[[ -n "$tag_version" ]] && return 0
+zi-log "{e} {b}gh-r{rst}: Could not determine tag version, cannot use bpick\"src\"."
return 1
fi
init_list=( ${(@f)"$( { .zinit-download-file-stdout $url || .zinit-download-file-stdout $url 1; } 2>/dev/null | command grep -i -o 'href=./'$user'/'$plugin'/releases/download/[^"]\+')"} )
init_list=(${(L)init_list[@]#href=?})
bpicks=(${(s.;.)ICE[bpick]})
[[ -z $bpicks ]] && bpicks=("")
local bpick bpick_error=""
reply=()
for bpick in "${bpicks[@]}"; do
list=($init_list)
if [[ -n $bpick ]]; then
list=( ${(M)list[@]:#(#i)*/$~bpick} )
if (( !$#list )); then
+zi-log "{e} {b}gh-r{rst}: {ice}bpick{rst} ice found no release assets To fix, modify the {ice}bpick{rst} glob pattern {glob}$bpick{rst}"
fi
else
local junk='*((s(ha256|ig|um)|386|asc|md5|txt|vsix)*|(apk|b3|deb|json|pkg|rpm|sh)(#e))|*.pkg.tar.zst|(*.zst~*.tar.zst)';
# print -l ${${(m@)list:#${~junk}}:t}
filtered=( ${(m@)list:#(#i)${~junk}} ) && (( $#filtered > 0 )) && list=( ${filtered[@]} )
fi
local -a array=( $(print -rm "*(${MACHTYPE}|${VENDOR}|)*~^*(${parts[1]}|${(L)$(uname)})*" $list[@]) )
(( ${#array} > 0 )) && list=( ${array[@]} )
for part in "${parts[@]}"; do
if (( $#list > 1 )); then
filtered=( ${(M)list[@]:#(#i)*${~part}*} ) && (( $#filtered > 0 )) && list=( ${filtered[@]} )
else
break
fi
done
if (( $#list > 1 )) { filtered=( ${list[@]:#(#i)*.(sha[[:digit:]]#|asc)} ) && (( $#filtered > 0 )) && list=( ${filtered[@]} ); }
if (( !$#list )); then
+zi-log "{e} {b}gh-r{rst}: No GitHub release assets found for {glob}$tag_version{rst}"
return 1
fi
reply+=( "${list[1]}" )
done
[[ -n $reply ]]
} # ]]]
# FUNCTION: ziextract [[[
# If the file is an archive, it is extracted by this function.
# Executable permissions are determined solely by the execute bit already
# stored in the archive — i.e. whatever the package author intended.
# No heuristics (file(1), shebang scanning, etc.) are applied.
#
# $1 - url
# $2 - file
ziextract() {
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt extendedglob typesetsilent noshortloops # warncreateglobal
local -aU opt_move opt_move2 opt_norm opt_auto opt_nobkp
zparseopts -D -E -move=opt_move -move2=opt_move2 -norm=opt_norm \
-auto=opt_auto -nobkp=opt_nobkp || \
{ +zi-log "{info}[{pre}ziextract{info}]{error} Incorrect options given to" \
"\`{pre}ziextract{msg2}' (available are: {meta}--auto{msg2}," \
"{meta}--move{msg2}, {meta}--move2{msg2}, {meta}--norm{msg2}," \
"{meta}--nobkp{msg2}).{rst}"; return 1; }
local file="$1" ext="$2"
integer move=${${${(M)${#opt_move}:#0}:+0}:-1} \
move2=${${${(M)${#opt_move2}:#0}:+0}:-1} \
norm=${${${(M)${#opt_norm}:#0}:+0}:-1} \
auto=${${${(M)${#opt_auto}:#0}:+0}:-1} \
nobkp=${${${(M)${#opt_nobkp}:#0}:+0}:-1}
if (( auto )) {
# First try known file extensions
local -aU files
integer ret_val
files=( (#i)**/*.(zip|rar|7z|tgz|tbz|tbz2|tar.gz|tar.bz2|tar.7z|txz|tar.xz|tar.zst|gz|xz|tar|dmg|exe)~(*/*|.(_backup|git))/*(-.DN) )
for file ( $files ) {
ziextract "$file" $opt_move $opt_move2 $opt_norm $opt_nobkp ${${${#files}:#1}:+--nobkp}
ret_val+=$?
}
# Second, try to find the archive via `file' tool
if (( !${#files} )) {
local -aU output infiles stage2_processed archives
infiles=( **/*~(._zinit*|._backup|.git)(|/*)~*/*/*(-.DN) )
output=( ${(@f)"$(command file -- $infiles 2>&1)"} )
archives=( ${(M)output[@]:#(#i)(* |(#s))(zip|rar|xz|7-zip|gzip|bzip2|tar|exe|PE32) *} )
for file ( $archives ) {
local fname=${(M)file#(${(~j:|:)infiles}): } desc=${file#(${(~j:|:)infiles}): } type
fname=${fname%%??}
[[ -z $fname || -n ${stage2_processed[(r)$fname]} ]] && continue
type=${(L)desc/(#b)(#i)(* |(#s))(zip|rar|xz|7-zip|gzip|bzip2|tar|exe|PE32) */$match[2]}
if [[ $type = (zip|rar|xz|7-zip|gzip|bzip2|tar|exe|pe32) ]] {
(( !OPTS[opt_-q,--quiet] )) && \
+zi-log "{info}[{pre}ziextract{info}]{msg2} detected a {meta}$type{rst} archive in the file {file}$fname{rst}."
ziextract "$fname" "$type" $opt_move $opt_move2 $opt_norm --norm ${${${#archives}:#1}:+--nobkp}
integer iret_val=$?
ret_val+=iret_val
(( iret_val )) && continue
# Support nested tar.(bz2|gz|…) archives
local infname=$fname
[[ -f $fname.out ]] && fname=$fname.out
files=( *.tar(ND) )
if [[ -f $fname || -f ${fname:r} ]] {
local -aU output2 archives2
output2=( ${(@f)"$(command file -- "$fname"(N) "${fname:r}"(N) $files[1](N) 2>&1)"} )
archives2=( ${(M)output2[@]:#(#i)(* |(#s))(zip|rar|xz|7-zip|gzip|bzip2|tar|exe|PE32) *} )
local file2
for file2 ( $archives2 ) {
fname=${file2%:*} desc=${file2##*:}
local type2=${(L)desc/(#b)(#i)(* |(#s))(zip|rar|xz|7-zip|gzip|bzip2|tar|exe|PE32) */$match[2]}
if [[ $type != $type2 && \
$type2 = (zip|rar|xz|7-zip|gzip|bzip2|tar)
]] {
# TODO: if multiple archives are really in the archive,
# this might delete too soon… However, it's unusual case.
[[ $fname != $infname && $norm -eq 0 ]] && command rm -f "$infname"
(( !OPTS[opt_-q,--quiet] )) && \
+zi-log "{info}[{pre}ziextract{info}]{msg2} detected a {obj}${type2}{rst} archive in the file {file}${fname}{rst}."
ziextract "$fname" "$type2" $opt_move $opt_move2 $opt_norm ${${${#archives}:#1}:+--nobkp}
ret_val+=$?
stage2_processed+=( $fname )
if [[ $fname == *.out ]] {
[[ -f $fname ]] && command mv -f "$fname" "${fname%.out}"
stage2_processed+=( ${fname%.out} )
}
}
}
}
}
}
}
return $ret_val
}
if [[ -z $file ]] {
+zi-log "{info}[{pre}ziextract{info}]{error} argument needed (the file to extract) or the {meta}--auto{msg} option."
return 1
}
if [[ ! -e $file ]] {
+zi-log "{info}[{pre}ziextract{info}]{error} ERROR:{msg} the file \`{meta}${file}{msg}' doesn't exist.{rst}"
return 1
}
if (( !nobkp )) {
command mkdir -p ._backup
command rm -rf ._backup/*(DN)
command mv -f *~(._zinit*|._backup|.git|.svn|.hg|$file)(DN) ._backup 2>/dev/null
}
.zinit-extract-wrapper() {
local file="$1" fun="$2" retval
(( !OPTS[opt_-q,--quiet] )) && \
+zi-log "{info}[{pre}ziextract{info}]{rst} Unpacking the files from: \`{obj}$file{msg}'{…}{rst}"
$fun; retval=$?
if (( retval == 0 )) {
local -a files
files=( *~(._zinit*|._backup|.git|.svn|.hg|$file)(DN) )
(( ${#files} && !norm )) && command rm -f "$file"
}
return $retval
}
→zinit-check() { (( ${+commands[$1]} )) || \
+zi-log "{info}[{pre}ziextract{info}]{error} Error:{msg} No command {data}$1{msg}, it is required to unpack {file}$2{rst}."
}
case "${${ext:+.$ext}:-$file}" in
((#i)*.zip)
→zinit-extract() { →zinit-check unzip "$file" || return 1; command unzip -qq -o "$file"; }
;;
((#i)*.rar)
→zinit-extract() { →zinit-check unrar "$file" || return 1; command unrar x "$file"; }
;;
((#i)*.tar.bz2|(#i)*.tbz|(#i)*.tbz2)
→zinit-extract() { →zinit-check bzip2 "$file" || return 1; command bzip2 -dc "$file" | command tar --no-same-owner -xf -; }
;;
((#i)*.tar.gz|(#i)*.tgz)
→zinit-extract() { →zinit-check gzip "$file" || return 1; command gzip -dc "$file" | command tar --no-same-owner -xf -; }
;;
((#i)*.tar.xz|(#i)*.txz)
→zinit-extract() { →zinit-check xz "$file" || return 1; command xz -dc "$file" | command tar --no-same-owner -xf -; }
;;
((#i)*.tar.7z|(#i)*.t7z)
→zinit-extract() { →zinit-check 7z "$file" || return 1; command 7z x -so "$file" | command tar --no-same-owner -xf -; }
;;
((#i)*.tar.zst)
→zinit-extract() { →zinit-check zstd "$file" || return 1; command zstd -dc "$file" | command tar --no-same-owner -xf -; }
;;
((#i)*.tar)
→zinit-extract() { →zinit-check tar "$file" || return 1; command tar --no-same-owner -xf "$file"; }
;;
((#i)*.gz|(#i)*.gzip)
if [[ $file != (#i)*.gz ]] {
command mv $file $file.gz
file=$file.gz
integer zi_was_renamed=1
}
→zinit-extract() {
→zinit-check gunzip "$file" || return 1
.zinit-get-mtime-into "$file" 'ZINIT[tmp]'
command gunzip "$file" |& command grep -E -v '.out$'
integer ret=$pipestatus[1]
command touch -t "$(strftime %Y%m%d%H%M.%S $ZINIT[tmp])" "$file"
return ret
}
;;
((#i)*.bz2|(#i)*.bzip2)
# Rename file if its extension does not match "bz2". bunzip2 refuses
# to operate on files that are not named correctly.
# See https://github.com/zdharma-continuum/zinit/issues/105
if [[ $file != (#i)*.bz2 ]] {
command mv $file $file.bz2
file=$file.bz2
}
→zinit-extract() { →zinit-check bunzip2 "$file" || return 1
.zinit-get-mtime-into "$file" 'ZINIT[tmp]'
command bunzip2 "$file" |& command grep -E -v '.out$'
integer ret=$pipestatus[1]
command touch -t "$(strftime %Y%m%d%H%M.%S $ZINIT[tmp])" "$file"
return ret
}
;;
((#i)*.xz)
if [[ $file != (#i)*.xz ]] {
command mv $file $file.xz
file=$file.xz
}
→zinit-extract() { →zinit-check xz "$file" || return 1
.zinit-get-mtime-into "$file" 'ZINIT[tmp]'
command xz -d "$file"
integer ret=$?
command touch -t "$(strftime %Y%m%d%H%M.%S $ZINIT[tmp])" "$file"
return ret
}
;;
((#i)*.7z|(#i)*.7-zip)
→zinit-extract() { →zinit-check 7z "$file" || return 1; command 7z x "$file" >/dev/null; }
;;
((#i)*.dmg)
→zinit-extract() {
local prog
for prog ( hdiutil cp ) { →zinit-check $prog "$file" || return 1; }
integer retval
local attached_vol="$( command hdiutil attach "$file" | \
command tail -n1 | command cut -f 3 )"
command cp -Rf ${attached_vol:-${TMPDIR:-/tmp}/acb321GEF}/*(D) .
retval=$?
command hdiutil detach $attached_vol
if (( retval )) {
+zi-log "{info}[{pre}ziextract{info}]{error} Error:{msg} problem occurred when attempted to copy the files" \
"from the mounted image: \`{obj}${file}{msg}'.{rst}"
}
return $retval
}
;;
((#i)*.deb)
→zinit-extract() { →zinit-check dpkg-deb "$file" || return 1; command dpkg-deb -R "$file" .; }
;;
((#i)*.rpm)
→zinit-extract() { →zinit-check cpio "$file" || return 1; $ZINIT[BIN_DIR]/share/rpm2cpio.zsh "$file" | command cpio -imd --no-absolute-filenames; }
;;
((#i)*.exe|(#i)*.pe32)
→zinit-extract() {
command chmod a+x -- ./$file
./$file /S /D="`cygpath -w $PWD`"
}
;;
esac
if [[ $(typeset -f + →zinit-extract) == "→zinit-extract" ]] {
.zinit-extract-wrapper "$file" →zinit-extract || {
+zi-log -n "{info}[{pre}ziextract{info}]{error} Error:{msg} extraction of the archive \`{file}${file}{msg}' had problems"
local -a bfiles
bfiles=( ._backup/*(DN) )
if (( ${#bfiles} && !nobkp )) {
+zi-log -n ", restoring the previous version of the plugin/snippet"
command mv ._backup/*(DN) . 2>/dev/null
}
+zi-log ".{rst}"
unfunction -- →zinit-extract →zinit-check 2>/dev/null
return 1
}
unfunction -- →zinit-extract →zinit-check
} else {
integer warning=1
# Not an archive and no explicit type claimed — treat as a plain single
# file (e.g. a bare gh-r release binary). HTTP downloads carry no exec
# bit, so mark the file executable and let the execs collection below
# pick it up and report success.
if [[ -z $ext ]] {
warning=0
(( !OPTS[opt_-q,--quiet] )) && \
+zi-log "{info}[{pre}ziextract{info}]{rst}" \
"\`{file}${file}{rst}' is not an archive — keeping it as a plain file."
command chmod a+x "$file"
}
}
unfunction -- .zinit-extract-wrapper
# Glob qualifier legend:
# (DN-.) — D=include dotfiles, N=null glob (no error if empty),
# -=no symlinks, .=regular files → all regular files
# (DN-*.) — same plus *=has execute bit set → files already marked
# executable by the archive extractor
local -aU execs
# Collect files that already have the execute bit set in the archive.
# This is the authoritative signal: if the package author wanted a file
# executable, they set +x when creating the archive. Any file that lacks
# +x in the archive (library, documentation, data file, …) should stay
# non-executable regardless of its content or extension.
# If a poorly maintained package fails to set permissions correctly,
# the user can fix it with the atclone/atpull ices — there is no need
# for zinit to second-guess the archive on every install.
execs=( **/*~(._zinit(|/*)|.git(|/*)|.svn(|/*)|.hg(|/*)|._backup(|/*))(DN-*.) )
builtin print -rl -- ${execs[@]} >! ${TMPDIR:-/tmp}/zinit-execs.$$.lst
if [[ ${#execs} -gt 0 ]] {
command chmod a+x "${execs[@]}"
if (( !OPTS[opt_-q,--quiet] )) {
if (( ${#execs} == 1 )); then
+zi-log "{info}[{pre}ziextract{info}]{rst} Successfully extracted and assigned +x chmod to the file: {obj}${execs[1]}{rst}."
else
local sep="$ZINIT[col-rst],$ZINIT[col-obj] "
if (( ${#execs} > 7 )) {
+zi-log "{info}[{pre}ziextract{info}]{rst} Successfully" \
"extracted and marked executable the appropriate files" \
"({obj}${(pj:$sep:)${(@)execs[1,5]:t}},…{rst}) contained" \
"in \`{file}$file{rst}'. All the extracted" \
"{obj}${#execs}{rst} executables are" \
"available in the {msg2}INSTALLED_EXECS{rst}" \
"array."
} else {
+zi-log "{info}[{pre}ziextract{info}]{rst} Successfully" \
"extracted and marked {obj}${#execs}{rst} executable the appropriate files" \
"({obj}${(pj:$sep:)${execs[@]:t}}{rst}) contained" \
"in \`{file}$file{rst}'."
}
fi
}
} elif (( warning )) {
+zi-log "{info}[{pre}ziextract{info}]{error} Error:{msg} didn't recognize archive type of {obj}${file}{msg} ${ext:+/ {obj2}${ext}{msg} } (no extraction has been done).{rst}"
}
if (( move | move2 )) {
local -a files
files=( *~(._zinit|.git|._backup|.tmp231ABC)(DN/) )
if (( ${#files} )) {
command mkdir -p .tmp231ABC
command mv -f *~(._zinit|.git|._backup|.tmp231ABC)(D) .tmp231ABC
if (( !move2 )) {
command mv -f **/*~(*/*~*/*/*|*/*/*/*|^*/*|._zinit(|/*)|.git(|/*)|._backup(|/*))(DN) .
} else {
command mv -f **/*~(*/*~*/*/*/*|*/*/*/*/*|^*/*|._zinit(|/*)|.git(|/*)|._backup(|/*))(DN) .
}
command mv .tmp231ABC/$file . &>/dev/null
command rm -rf .tmp231ABC
}
REPLY="${${execs[1]:h}:h}/${execs[1]:t}"
} else {
REPLY="${execs[1]}"
}
return 0
} # ]]]
# FUNCTION: .zinit-extract [[[
.zinit-extract() {
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt extendedglob warncreateglobal typesetsilent
local tpe=$1 extract=$2 local_dir=$3
(
builtin cd -q "$local_dir" || \
{ +zi-log "{error}ERROR:{msg2} The path of the $tpe" \
"(\`{file}$local_dir{msg2}') isn't accessible.{rst}"
return 1
}
local -aU files
files=( ${(@)${(@s: :)${extract##(\!-|-\!|\!|-)}}//(#b)(((#s)|([^\\])[\\]([\\][\\])#)|((#s)|([^\\])([\\][\\])#)) /${match[2]:+$match[3]$match[4] }${match[5]:+$match[6]${(l:${#match[7]}/2::\\:):-} }} )
if [[ ${#files} -eq 0 && -n ${extract##(\!-|-\!|\!|-)} ]] {
+zi-log "{error}ERROR:{msg2} The files" \
"(\`{file}${extract##(\!-|-\!|\!|-)}{msg2}')" \
"not found, cannot extract.{rst}"
return 1
} else {
(( !${#files} )) && files=( "" )
}
local file
for file ( "${files[@]}" ) {
[[ -z $extract ]] && local auto2=--auto
ziextract ${${(M)extract:#(\!|-)##}:+--auto} \
$auto2 $file \
${${(MS)extract[1,2]##-}:+--norm} \
${${(MS)extract[1,2]##\!}:+--move} \
${${(MS)extract[1,2]##\!\!}:+--move2} \
${${${#files}:#1}:+--nobkp}
}
)
} # ]]]
# FUNCTION: .zinit-at-eval [[[
.zinit-at-eval() {
local atpull="$1" atclone="$2"
integer retval
@zinit-substitute atclone atpull
local cmd="$atpull"
[[ $atpull == "%atclone" ]] && cmd="$atclone"
eval "$cmd"
return "$?"
} # ]]]
# FUNCTION: .zinit-get-cygwin-package [[[
.zinit-get-cygwin-package() {
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt extendedglob warncreateglobal typesetsilent noshortloops rcquotes
REPLY=
local pkg=$1 nl=$'\n'
integer retry=3
#
# Download mirrors.lst
#
+zi-log "{info}Downloading{ehi}: {obj}mirrors.lst{info}{…}{rst}"
local mlst="$(mktemp)"
while (( retry -- )) {
if ! .zinit-download-file-stdout https://cygwin.com/mirrors.lst 0 > $mlst; then
.zinit-download-file-stdout https://cygwin.com/mirrors.lst 1 > $mlst
fi
local -a mlist
mlist=( "${(@f)$(<$mlst)}" )
local mirror=${${mlist[ RANDOM % (${#mlist} + 1) ]}%%;*}
[[ -n $mirror ]] && break
}
if [[ -z $mirror ]] {
+zi-log "{error}Couldn't download{error}: {obj}mirrors.lst {error}."
return 1
}
mirror=http://ftp.eq.uc.pt/software/pc/prog/cygwin/
#
# Download setup.ini.bz2
#
+zi-log "{info2}Selected mirror is{error}: {url}${mirror}{rst}"
+zi-log "{info}Downloading{ehi}: {file}setup.ini.bz2{info}{…}{rst}"
local setup="$(mktemp -u)"
retry=3
while (( retry -- )) {
if ! .zinit-download-file-stdout ${mirror}x86_64/setup.bz2 0 1 > $setup.bz2; then
.zinit-download-file-stdout ${mirror}x86_64/setup.bz2 1 1 > $setup.bz2
fi
command bunzip2 "$setup.bz2" 2>/dev/null
[[ -s $setup ]] && break
mirror=${${mlist[ RANDOM % (${#mlist} + 1) ]}%%;*}
+zi-log "{pre}Retrying{error}: {meta}#{obj}$(( 3 - $retry ))/3, {pre}with mirror{error}: {url}${mirror}{rst}"
}
local setup_contents="$(command grep -A 26 "@ $pkg\$" "$setup")"
local urlpart=${${(S)setup_contents/(#b)*@ $pkg${nl}*install: (*)$nl*/$match[1]}%% *}
if [[ -z $urlpart ]] {
+zi-log "{error}Couldn't find package{error}: {data2}\`{data}${pkg}{data2}'{error}.{rst}"
return 2
}
local url=$mirror/$urlpart outfile=${TMPDIR:-${TMPDIR:-/tmp}}/${urlpart:t}
#
# Download the package
#
+zi-log "{nl}{i} Downloading {b}{file}${url:t}{rst}"
retry=2
while (( retry -- )) {
integer retval=0
if ! .zinit-download-file-stdout $url 0 1 > $outfile; then
if ! .zinit-download-file-stdout $url 1 1 > $outfile; then
+zi-log "{error}Couldn't download{error}: {url}${url}{error}."
retval=1
mirror=${${mlist[ RANDOM % (${#mlist} + 1) ]}%%;*}
url=$mirror/$urlpart outfile=${TMPDIR:-${TMPDIR:-/tmp}}/${urlpart:t}
if (( retry )) {
+zi-log "{info2}Retrying, with mirror{error}: {url}${mirror}{info2}{…}{rst}"
continue
}
fi
fi
break
}
REPLY=$outfile
} # ]]]
# FUNCTION: zicp [[[
zicp() {
builtin emulate -LR zsh ${=${options[xtrace]:#off}:+-o xtrace}
setopt extendedglob warncreateglobal typesetsilent noshortloops rcquotes
local -a mbegin mend match
local cmd=cp
if [[ $1 = (-m|--mv) ]] { cmd=mv; shift; }
local dir
if [[ $1 = (-d|--dir) ]] { dir=$2; shift 2; }
local arg
arg=${${(j: :)@}//(#b)(([[:space:]]~ )#(([^[:space:]]| )##)([[:space:]]~ )#(#B)(->|=>|→)(#B)([[:space:]]~ )#(#b)(([^[:space:]]| )##)|(#B)([[:space:]]~ )#(#b)(([^[:space:]]| )##))/${match[3]:+$match[3] $match[6]\;}${match[8]:+$match[8] $match[8]\;}}
(
if [[ -n $dir ]] { cd $dir || return 1; }
local a b var
integer retval
for a b ( "${(s: :)${${(@s.;.)${arg%\;}}:-* .}}" ) {
for var ( a b ) {
: ${(P)var::=${(P)var//(#b)(((#s)|([^\\])[\\]([\\][\\])#)|((#s)|([^\\])([\\][\\])#)) /${match[2]:+$match[3]$match[4] }${match[5]:+$match[6]${(l:${#match[7]}/2::\\:):-} }}}
}
if [[ $a != *\** ]] { a=${a%%/##}"/*" }
command mkdir -p ${~${(M)b:#/*}:-$ZPFX/$b}
command $cmd -f ${${(M)cmd:#cp}:+-R} $~a ${~${(M)b:#/*}:-$ZPFX/$b}
retval+=$?
}
return $retval
)
return
} # ]]]
# FUNCTION: zimv [[[
zimv() {
local dir
if [[ $1 = (-d|--dir) ]] { dir=$2; shift 2; }
zicp --mv ${dir:+--dir} $dir "$@"
} # ]]]
# FUNCTION: ∞zinit-reset-hook [[[
∞zinit-reset-hook() {
# File
if [[ "$1" = plugin ]] {
local type="$1" user="$2" plugin="$3" id_as="$4" dir="${5#%}" hook="$6"
} else {
local type="$1" url="$2" id_as="$3" dir="${4#%}" hook="$5"
}
if (( ( OPTS[opt_-r,--reset] && ZINIT[-r/--reset-opt-hook-has-been-run] == 0 ) || \
( ${+ICE[reset]} && ZINIT[-r/--reset-opt-hook-has-been-run] == 1 )
)) {
if (( ZINIT[-r/--reset-opt-hook-has-been-run] )) {
local msg_bit="{meta}reset{msg2} ice given{pre}" option=
} else {
local msg_bit="{meta2}-r/--reset{msg2} given to \`{meta}update{pre}'" option=1
}
if [[ $type == snippet ]] {
if (( $+ICE[svn] )) {
if [[ $skip_pull -eq 0 && -d $filename/.svn ]] {
(( !OPTS[opt_-q,--quiet] )) && +zi-log "{pre}reset ($msg_bit): {msg2}Resetting the repository ($msg_bit) with command: {rst}svn revert --recursive {…}/{file}$filename/.{rst} {…}"
command svn revert --recursive $filename/.
}
} else {
if (( ZINIT[annex-multi-flag:pull-active] >= 2 )) {
if (( !OPTS[opt_-q,--quiet] )) {
if [[ -f $local_dir/$dirname/$filename ]] {
if [[ -n $option || -z $ICE[reset] ]] {
+zi-log "{pre}reset ($msg_bit):{msg2} Removing the snippet-file: {file}$filename{msg2} {…}{rst}"
} else {
+zi-log "{pre}reset ($msg_bit):{msg2} Removing the snippet-file: {file}$filename{msg2}," \
"with the supplied code: {data2}$ICE[reset]{msg2} {…}{rst}"
}
if (( option )) {
command rm -f "$local_dir/$dirname/$filename"
} else {
eval "${ICE[reset]:-rm -f \"$local_dir/$dirname/$filename\"}"
}
} else {
+zi-log "{pre}reset ($msg_bit):{msg2} The file {file}$filename{msg2} is already deleted {…}{rst}"
if [[ -n $ICE[reset] && ! -n $option ]] {
+zi-log "{pre}reset ($msg_bit):{msg2} (skipped running the provided reset-code:" \
"{data2}$ICE[reset]{msg2}){rst}"
}
}
}
} else {
[[ -f $local_dir/$dirname/$filename ]] && \
+zi-log "{pre}reset ($msg_bit): {msg2}Skipping the removal of {file}$filename{msg2}" \
"as there is no new copy scheduled for download.{rst}" || \
+zi-log "{pre}reset ($msg_bit): {msg2}The file {file}$filename{msg2} is already deleted" \
"and {ehi}no new download is being scheduled.{rst}"
}
}
} elif [[ $type == plugin ]] {
if (( is_release && !skip_pull )) {
if (( option )) {
(( !OPTS[opt_-q,--quiet] )) && +zi-log "{pre}reset ($msg_bit): {msg2}running: {rst}rm -rf ${${ZINIT[PLUGINS_DIR]:#[/[:space:]]##}:-${TMPDIR:-/tmp}/xyzabc312}/${${(M)${local_dir##${ZINIT[PLUGINS_DIR]}[/[:space:]]#}:#[^/]*}:-${TMPDIR:-/tmp}/xyzabc312-zinit-protection-triggered}/*"
builtin eval command rm -rf ${${ZINIT[PLUGINS_DIR]:#[/[:space:]]##}:-${TMPDIR:-/tmp}/xyzabc312}/"${${(M)${local_dir##${ZINIT[PLUGINS_DIR]}[/[:space:]]#}:#[^/]*}:-${TMPDIR:-/tmp}/xyzabc312-zinit-protection-triggered}"/*(ND)
} else {
(( !OPTS[opt_-q,--quiet] )) && +zi-log "{pre}reset ($msg_bit): {msg2}running: {rst}${ICE[reset]:-rm -rf ${${ZINIT[PLUGINS_DIR]:#[/[:space:]]##}:-${TMPDIR:-/tmp}/xyzabc312}/${${(M)${local_dir##${ZINIT[PLUGINS_DIR]}[/[:space:]]#}:#[^/]*}:-${TMPDIR:-/tmp}/xyzabc312-zinit-protection-triggered}/*}"
builtin eval ${ICE[reset]:-command rm -rf ${${ZINIT[PLUGINS_DIR]:#[/[:space:]]##}:-${TMPDIR:-/tmp}/xyzabc312}/"${${(M)${local_dir##${ZINIT[PLUGINS_DIR]}[/[:space:]]#}:#[^/]*}:-${TMPDIR:-/tmp}/xyzabc312-zinit-protection-triggered}"/*(ND)}
}
} elif (( !skip_pull )) {
if (( option )) {
+zi-log "{pre}reset ($msg_bit): {msg2}Resetting the repository with command:{rst} git reset --hard HEAD {…}"
command git reset --hard HEAD
} else {
+zi-log "{pre}reset ($msg_bit): {msg2}Resetting the repository with command:{rst} ${ICE[reset]:-git reset --hard HEAD} {…}"
builtin eval "${ICE[reset]:-git reset --hard HEAD}"
}
}
}
}
if (( OPTS[opt_-r,--reset] )) {
if (( ZINIT[-r/--reset-opt-hook-has-been-run] == 1 )) {
ZINIT[-r/--reset-opt-hook-has-been-run]=0
} else {
ZINIT[-r/--reset-opt-hook-has-been-run]=1
}
} else {
# If theres no -r/--reset, pretend that it already has been served.
ZINIT[-r/--reset-opt-hook-has-been-run]=1
}
} # ]]]
# FUNCTION: ∞zinit-configure-base-hook [[[
# A base common implementation of the configure ice
∞zinit-configure-base-hook () {
emulate -L zsh
setopt extendedglob
if [[ "$1" = plugin ]]; then
local dir="${5#%}" hook="$6" subtype="$7" ex="$8"
else
local dir="${4#%}" hook="$5" subtype="$6" ex="$7"
fi
local flags configure eflags aflags ice='{b}configure{rst}:'
configure=${ICE[configure]}
@zinit-substitute configure
(( ${+ICE[configure]} )) || return 0
flags=${(M)configure##[smc0\!\#]##}
configure=${configure##$flags([[:space:]]##|(#e))}
eflags=${(SM)flags##[\!]##}
aflags=${(SM)flags##[smc0]##}
[[ $eflags == $ex ]] || return 0
typeset -aU configure_opt=(${(@s; ;)configure})
configure_opt+=("--prefix=${ZPFX:-${ZINIT[HOME_DIR]}/polaris}")
local ___oldcd=$PWD ___oldoldpwd=$OLDPWD
{
.zinit-cd-quiet "$dir" || return 1
if [[ -n *(#i)makefile(#qN) ]]; then
return 0
elif [[ -z *(#i)configure(#qN) ]]; then
+zi-log "{m} ${ice} Attempting to generate configure script... "
local c
for c in "[[ -e autogen.sh ]] && sh ./autogen.sh" "[[ -n *.a[mc](#qN.) ]] && autoreconf -ifm" "git clean -fxd; aclocal --force; autoconf --force; automake --add-missing --copy --force-missing"; do
+zi-log -PrD "{dbg} ${ice} {faint}${c}{rst}"
{
eval "${c}" 2> /dev/null >&2
} always {
[[ -n *(#i)configure(#qN) ]] && break
(( TRY_BLOCK_ERROR = 0 ))
}
done
fi
+zi-log "{m} ${ice} Generating Makefile"
+zi-log "{dbg} ${ice} {faint}./configure $(builtin print -PDn -- ${(Ds; ;)configure_opt[@]//prefix /prefix=}){rst}"
eval "./configure ${(S)configure_opt[@]//prefix /prefix=}" 2> /dev/null >&2
if [[ -n *(#i)makefile(#qN) ]]; then
+zi-log "{m} ${ice} Successfully generated Makefile"
return 0
else
+zi-log "{e} ${ice} Failed project configuration"
return 1
fi
} always {
.zinit-restore-dir "$___oldcd" "$___oldoldpwd"
}
} # ]]]
# FUNCTION: ∞zinit-configure-e-hook [[[
∞zinit-configure-e-hook() {
∞zinit-configure-base-hook "$@" "!"
} # ]]]
# FUNCTION: ∞zinit-configure-hook [[[
# The non-! version of configure'' ice. Runs in between
# of make'!' and make''. Configure script naturally runs
# before make.
∞zinit-configure-hook() {
∞zinit-configure-base-hook "$@" ""
} # ]]]
# FUNCTION: ∞zinit-make-base-hook [[[
# A base common implementation of the make ice
∞zinit-make-base-hook () {
emulate -L zsh
setopt extendedglob
[[ -z $ICE[make] ]] && return 0
if [[ "$1" = plugin ]]; then
local dir="${5#%}" hook="$6" subtype="$7" ex="$8"
else
local dir="${4#%}" hook="$5" subtype="$6" ex="$7"
fi
local make=${ICE[make]} ice='{b}make{rst}:'
@zinit-substitute make
(( ${+ICE[make]} )) || return 0
local eflags=${(M)make##[\!]##}
make=${make##$eflags}
[[ $ex == $eflags ]] || return 0
local make_prefix='prefix'
if grep -w -- "PREFIX =" ${dir}/[Mm]akefile >/dev/null; then
make_prefix="PREFIX"
fi
local src=($dir/[Cc][Mm]ake*(N.om[1]))
if (( $#src )); then
+zi-log "{m} ${ice} Detected Cmake project, using CMAKE_INSTALL_PREFIX={file}\$ZPFX{rst}"
make_prefix="CMAKE_INSTALL_PREFIX"
else
+zi-log -ru2 -- "{dbg} ${dir:t}: No Cmake files found in ${dir}"
fi
local prefix="${ZINIT[ZPFX]}"
if [[ -n OPTS[opt_-q,--quiet] || -n ${ZINIT[DEBUG]:#1} ]]; then
+zi-log "{dbg} ${ice} setting quiet mode"
local quiet='2>/dev/null 1>&2'
fi
local -i ret=0
{
build="make -C ${dir} --jobs 4"
+zi-log "{m} ${ice} Building..."
# +zi-log "{m} ${ice} {faint}${(Ds; ;)build} $make_prefix=$(builtin print -Pnf '%s' ${(D)ZINIT[ZPFX]}){rst}"
+zi-log "{dbg} ${ice} eval ${build} $make_prefix=$prefix 2>/dev/null 1>&2"
eval "${build} $make_prefix=$prefix" 2>/dev/null 1>&2
ret=$?
} always {
if (( ret )); then
+zi-log "{w} ${ice} Build returned {num}${ret}{rst}"
fi
(( TRY_BLOCK_ERROR = 0 ))
}
{
install="${build} ${make}"
# +zi-log "{m} ${ice} {faint}${(Ds; ;)build} $make_prefix=$(builtin print -Pnf '%s' ${ZINIT[POLARIS]}) ${make} {rst}"
+zi-log "{m} ${ice} Installing in ${(D)ZINIT[ZPFX]}"
+zi-log "{dbg} ${ice} eval ${build} $make_prefix=$prefix ${make} 2>/dev/null 1>&2"
eval "${(s; ;)install} $make_prefix=$prefix" 2>/dev/null 1>&2
ret=$?
} always {
if (( ret )); then
+zi-log "{w} ${ice} Install returned {num}${ret}{rst}"
fi
(( TRY_BLOCK_ERROR = 0 ))
}
return $ret
} # ]]]
# FUNCTION: ∞zinit-make-e-hook [[[
∞zinit-make-e-hook() {
∞zinit-make-base-hook "$@" "!"
} # ]]]
# FUNCTION: ∞zinit-make-ee-hook [[[
∞zinit-make-ee-hook() {
∞zinit-make-base-hook "$@" "!!"
} # ]]]
# FUNCTION: ∞zinit-make-hook [[[
∞zinit-make-hook() {
∞zinit-make-base-hook "$@" ""
} # ]]]
# FUNCTION: __zinit-cmake-base-hook [[[
# A base common implementation of the cmake ice
__zinit-cmake-base-hook () {
emulate -L zsh
setopt extended_glob
(( ${+ICE[cmake]} )) || return 0
if (( ! ${+commands[cmake]} )); then
+zi-log "{e} {cmd}cmake{rst} required to use {ice}cmake{rst} ice"
return 0
fi
if [[ "$1" = plugin ]]; then
local dir="${5#%}" hook="$6" subtype="$7" ex="$8"
else
local dir="${4#%}" hook="$5" subtype="$6" ex="$7"
fi
(( OPTS[opt_-q,--quiet] || ZINIT[DEBUG] )) && local QUIET='2>/dev/null 1>&2'
local c ret=0 ice='{b}cmake{rst}:'
for c in "-S ${dir} -B ${dir}/build -DCMAKE_BUILD_TYPE=Release --install-prefix ${ZINIT[ZPFX]} ${QUIET}" "--build ${dir}/build --parallel $(nproc) ${QUIET}" "--install ${dir}/build ${QUIET}"; do
+zi-log "{m} ${ice} {faint}cmake ${(Ds; ;)c} {rst}"
eval "cmake ${c}" 2> /dev/null >&2
if (( $? )); then
+zi-log "{e} ${ice} Failure cmake ${c}{rst}"
ret=$?
fi
done
return $?
} # ]]]
# FUNCTION: +zinit-cmake-hook [[[
+zinit-cmake-hook() {
__zinit-cmake-base-hook "$@"
} # ]]]
# FUNCTION: ∞zinit-atclone-hook [[[
∞zinit-atclone-hook() {
[[ "$1" = plugin ]] && \
local dir="${5#%}" hook="$6" subtype="$7" || \
local dir="${4#%}" hook="$5" subtype="$6"
local atclone=${ICE[atclone]}
@zinit-substitute atclone
(( ${+ICE[atclone]} )) || return 0
local rc=0
[[ -n $atclone ]] && .zinit-countdown atclone && {
local ___oldcd=$PWD ___oldoldpwd=$OLDPWD
(( ${+ICE[nocd]} == 0 )) && .zinit-cd-quiet "$dir"
# Unlike its atpull siblings this evals inline, with no .zinit-at-eval
# frame to absorb a `return' from the ice body.
{
eval "$atclone"
rc="$?"
} always {
.zinit-restore-dir "$___oldcd" "$___oldoldpwd"
}
}
return "$rc"
} # ]]]
# FUNCTION: ∞zinit-extract-hook [[[
∞zinit-extract-hook() {
[[ "$1" = plugin ]] && \
local dir="${5#%}" hook="$6" subtype="$7" || \
local dir="${4#%}" hook="$5" subtype="$6"
local extract=${ICE[extract]}
@zinit-substitute extract
(( ${+ICE[extract]} )) || return 0
.zinit-extract plugin "$extract" "$dir"
} # ]]]
# FUNCTION: ∞zinit-cp-mv-operation-hook [[[
∞zinit-file-cp-mv-operation() {
local cmd="$1" # Either "cp" or "mv"
local ice_key="$cmd"
[[ -z $ICE[$ice_key] ]] && return 0
[[ "$2" = plugin ]] && \
local dir="${6#%}" hook="$7" subtype="$8" || \
local dir="${5#%}" hook="$6" subtype="$7"
# Parse and clean up the ICE directive
local -a pairs
pairs=( ${(s[;])ICE[$ice_key]} ) # Split on semicolons
pairs=( "${pairs[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" ) # Trim spaces
local pair retval=0
for pair in "${pairs[@]}"; do
if [[ $pair == *("->"|"→")* ]]; then
local from="${pair%%[[:space:]]#(->|→)*}"
local to="${pair##*(->|→)[[:space:]]#}"
else
local from="${pair%%[[:space:]]##*}"
local to="${pair##*[[:space:]]##}"
fi
@zinit-substitute from to
local -a cmd_args=("-f")
local -a afr
(
.zinit-cd-quiet "$dir" || return 1
afr=( ${~from}(DN) ) # Expand glob patterns
if (( ! ${#afr} )); then
+zi-log "{warn}Warning: $ice_key ice didn't match any file. [{error}$pair{warn}]" \
"{nl}{warn}Available files:{nl}{obj}$(ls -1)"
retval=1
continue
fi
if (( !OPTS[opt_-q,--quiet] )); then
cmd_args+=("-v")
fi
for file in "${afr[@]}"; do
command "$cmd" "${cmd_args[@]}" "$file" "$to" || retval=$?
# Handle .zwc files if they exist
command "$cmd" "${cmd_args[@]}" "$file.zwc" "$to.zwc" 2>/dev/null
done
)
done
return $retval
} # ]]]
# FUNCTION: ∞zinit-mv-hook [[[
∞zinit-mv-hook() {
∞zinit-file-cp-mv-operation "mv" "$@"
} # ]]]
# FUNCTION: ∞zinit-cp-hook [[[
∞zinit-cp-hook() {
∞zinit-file-cp-mv-operation "cp" "$@"
} # ]]]
# FUNCTION: ∞zinit-compile-plugin-hook [[[
∞zinit-compile-plugin-hook () {
if [[ "$1" = plugin ]]; then
local dir="${5#%}" hook="$6" subtype="$7"
else
local dir="${4#%}" hook="$5" subtype="$6"
fi
if ! [[ ( $hook = *\!at(clone|pull)* && ${+ICE[nocompile]} -eq 0 ) || ( $hook = at(clone|pull)* && $ICE[nocompile] = '!' ) ]]; then
return 0
fi
if [[ -z $ICE[(i)(\!|)(sh|bash|ksh|csh)] ]]; then
() {
builtin source "${ZINIT[BIN_DIR]}/zinit-autoload.zsh" || return 1
setopt local_options extended_glob warn_create_global
local quiet=1
if [[ $tpe == snippet ]]; then
.zinit-compile-plugin "%$dir"
else
.zinit-compile-plugin "$id_as"
fi
}
fi
} # ]]]
# FUNCTION: ∞zinit-atpull-e-hook [[[
∞zinit-atpull-e-hook() {
(( ${+ICE[atpull]} )) || return 0
[[ -n ${ICE[atpull]} ]] || return 0
# Only process atpull"!cmd"
[[ $ICE[atpull] == "!"* ]] || return 0
[[ "$1" = plugin ]] && \
local dir="${5#%}" hook="$6" subtype="$7" || \
local dir="${4#%}" hook="$5" subtype="$6"
local atpull=${ICE[atpull]#\!}
local rc=0
.zinit-countdown atpull && {
local ___oldcd=$PWD ___oldoldpwd=$OLDPWD
(( ${+ICE[nocd]} == 0 )) && .zinit-cd-quiet "$dir"
.zinit-at-eval "$atpull" "$ICE[atclone]"
rc="$?"
.zinit-restore-dir "$___oldcd" "$___oldoldpwd"
}
return "$rc"
} # ]]]
# FUNCTION: ∞zinit-atpull-hook [[[
∞zinit-atpull-hook() {
(( ${+ICE[atpull]} )) || return 0
[[ -n ${ICE[atpull]} ]] || return 0
# Exit early if atpull"!cmd" -> this is done by zinit-atpull-e-hook
[[ $ICE[atpull] == "!"* ]] && return 0
[[ "$1" == plugin ]] && \
local dir="${5#%}" hook="$6" subtype="$7" || \
local dir="${4#%}" hook="$5" subtype="$6"
local atpull=${ICE[atpull]}
local rc=0
.zinit-countdown atpull && {
local ___oldcd=$PWD ___oldoldpwd=$OLDPWD
(( ${+ICE[nocd]} == 0 )) && .zinit-cd-quiet "$dir"
.zinit-at-eval "$atpull" $ICE[atclone]
rc="$?"
.zinit-restore-dir "$___oldcd" "$___oldoldpwd"
}
return "$rc"
} # ]]]
# FUNCTION: ∞zinit-ps-on-update-hook [[[
∞zinit-ps-on-update-hook() {
[[ -z $ICE[ps-on-update] ]] && return 0
[[ "$1" = plugin ]] && \
local tpe="$1" dir="${5#%}" hook="$6" subtype="$7" || \
local tpe="$1" dir="${4#%}" hook="$5" subtype="$6"
if (( !OPTS[opt_-q,--quiet] )) {
+zi-log "Running $tpe's provided update code: {info}${ICE[ps-on-update][1,50]}${ICE[ps-on-update][51]:+…}{rst}"
(
builtin cd -q "$dir" || return 1
eval "$ICE[ps-on-update]"
)
} else {
(
builtin cd -q "$dir" || return 1
eval "$ICE[ps-on-update]" &> /dev/null
)
}
} # ]]]
# vim: ft=zsh sw=2 ts=2 et foldmarker=[[[,]]] foldmethod=marker