Skip to content

Commit bf6a68a

Browse files
committed
refactor: migrate installer scripts to XDG paths and harden POSIX
install.sh: - Add set -eu; use WORKDIR=$(mktemp -d) with safe trap cleanup - Replace ~/.zi with XDG_DATA_HOME-aware path - Fix sed command for ZI[STREAM] substitution - Correct cd fallback from return to exit 1 - Guard branch pull with BOPT; add exit 1 on failed clone - Fix .zshrc loader snippet variable quoting install_zpmod.sh: - Add set -eu, file header and WORKDIR trap - Add pure-POSIX _zi_ver_ge() replacing expr string comparison - Honour XDG_DATA_HOME for ZI_HOME default - Replace exit 255 with exit 1 throughout lib/zsh/init.zsh: - Update default branch to use ZI[STREAM] parameter - Align loader paths with XDG layout
1 parent a810dc8 commit bf6a68a

3 files changed

Lines changed: 204 additions & 182 deletions

File tree

lib/sh/install.sh

Lines changed: 46 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
33
# vim: ft=sh sw=2 ts=2 et
44

5-
trap 'rm -rf "$WORKDIR"' EXIT INT
6-
WORKDIR="$(mktemp -d)"
5+
set -eu
6+
7+
WORKDIR="$(mktemp -d)" || exit 1
8+
trap 'rm -rf "${WORKDIR:?}"' EXIT INT TERM
79
ZOPT=""
810
AOPT=""
911
BOPT="main"
@@ -43,21 +45,21 @@ if [ "${AOPT}" = loader ]; then
4345
command wget -qO "${ZI_CONFIG_DIR}/init.zsh" https://raw.githubusercontent.com/z-shell/zi-src/main/lib/zsh/init.zsh
4446
fi
4547
command chmod go-w "${ZI_CONFIG_DIR}" && command chmod a+x "${ZI_CONFIG_DIR}/init.zsh"
46-
command sed -i "s/branch=\"main\"/branch=\"${BOPT}\"/g" "${ZI_CONFIG_DIR}/init.zsh"
48+
# shellcheck disable=SC2016
49+
command sed -i 's|: ${ZI\[STREAM\]:="main"}|: ${ZI[STREAM]:="'"${BOPT}"'"}|' "${ZI_CONFIG_DIR}/init.zsh"
4750
fi
4851

49-
if [ -z "${ZI_HOME}" ]; then
50-
ZI_HOME="${ZDOTDIR:-${HOME}}/.zi"
52+
if [ -z "${ZI_HOME-}" ]; then
53+
ZI_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}/zi"
5154
fi
5255

53-
if [ -z "${ZI_BIN_DIR_NAME}" ]; then
56+
if [ -z "${ZI_BIN_DIR_NAME-}" ]; then
5457
ZI_BIN_DIR_NAME="bin"
5558
fi
5659

5760
if ! test -d "${ZI_HOME}"; then
5861
command mkdir "${ZI_HOME}"
5962
command chmod go-w "${ZI_HOME}"
60-
command chmod go-w "${ZI_HOME}/${ZI_BIN_DIR_NAME}"
6163
fi
6264

6365
if ! command -v git >/dev/null 2>&1; then
@@ -68,31 +70,32 @@ fi
6870
# Get the download-progress bar tool
6971
if command -v curl >/dev/null 2>&1; then
7072
command mkdir -p /tmp/zi
71-
cd /tmp/zi || return
73+
cd /tmp/zi || exit 1
7274
command curl -fsSLO https://raw.githubusercontent.com/z-shell/zi/main/lib/zsh/git-process-output.zsh &&
7375
command chmod a+x /tmp/zi/git-process-output.zsh
7476
elif command -v wget >/dev/null 2>&1; then
7577
command mkdir -p /tmp/zi
76-
cd /tmp/zi || return
78+
cd /tmp/zi || exit 1
7779
command wget -q https://raw.githubusercontent.com/z-shell/zi/main/lib/zsh/git-process-output.zsh &&
7880
command chmod a+x /tmp/zi/git-process-output.zsh
7981
fi
8082

8183
if test -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}/.git"; then
82-
cd "${ZI_HOME}/${ZI_BIN_DIR_NAME}" || return
84+
cd "${ZI_HOME}/${ZI_BIN_DIR_NAME}" || exit 1
8385
printf '%s\n' "▓▒░ Updating (z-shell/zi) plugin manager at ${ZI_HOME}/${ZI_BIN_DIR_NAME}"
8486
command git clean -d -f -f
8587
command git reset --hard HEAD
86-
command git pull -q origin HEAD
88+
command git pull -q origin "${BOPT}"
8789
else
88-
cd "${ZI_HOME}" || return
90+
cd "${ZI_HOME}" || exit 1
8991
printf '%s\n' "▓▒░ Installing (z-shell/zi) plugin manager at ${ZI_HOME}/${ZI_BIN_DIR_NAME}"
9092
{ git clone --progress --depth=1 --branch "${BOPT}" https://github.com/z-shell/zi.git "${ZI_BIN_DIR_NAME}" \
9193
2>&1 | { /tmp/zi/git-process-output.zsh || cat; }; } 2>/dev/null
92-
if [ -d "${ZI_BIN_DIR_NAME}" ]; then
94+
if [ -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}" ]; then
9395
printf '%s\n' "▓▒░ Successfully installed at ${ZI_HOME}/${ZI_BIN_DIR_NAME}".
9496
else
9597
printf '%s\n' "▓▒░ Something went wrong, couldn't install ZI at ${ZI_HOME}/${ZI_BIN_DIR_NAME}"
98+
exit 1
9699
fi
97100
fi
98101

@@ -106,7 +109,7 @@ MAIN_PROFILE() {
106109
printf '%s\n' "▓▒░ Seems that .zshrc already has content or setup skipped - no changes will be made."
107110
ZOPT='skip'
108111
fi
109-
if [ "${ZOPT}" != skip ]; then
112+
if [ "${ZOPT}" != skip ] && [ "${AOPT}" != loader ]; then
110113
printf '%s\n' "▓▒░ Updating ${THE_ZDOTDIR}/.zshrc"
111114
ZI_HOME="$(echo "${ZI_HOME}" | sed "s|${HOME}|\$HOME|")"
112115
command cat <<-EOF >>"${THE_ZDOTDIR}/.zshrc"
@@ -126,10 +129,9 @@ EOF
126129
printf '%s\n' "▓▒░ Minimal configuration"
127130
fi
128131
if [ "${AOPT}" = loader ] && [ "${ZOPT}" != skip ]; then
129-
command rm -rf "${THE_ZDOTDIR}/.zshrc"
130132
command cat <<-EOF >>"${THE_ZDOTDIR}/.zshrc"
131-
if [[ -r "${XDG_CONFIG_HOME:-${HOME}/.config}/zi/init.zsh" ]]; then
132-
source "${XDG_CONFIG_HOME:-${HOME}/.config}/zi/init.zsh" && zzinit
133+
if [[ -r "\${XDG_CONFIG_HOME:-\${HOME}/.config}/zi/init.zsh" ]]; then
134+
source "\${XDG_CONFIG_HOME:-\${HOME}/.config}/zi/init.zsh" && zzinit
133135
fi
134136
EOF
135137
printf '%s\n' "▓▒░ Loader added"
@@ -164,86 +166,38 @@ EOF
164166
fi
165167
}
166168

167-
SETUP_ZPMOD() {
168-
if ! test -d "${ZI_HOME}/${MOD_HOME}"; then
169-
command mkdir -p "${ZI_HOME}/${MOD_HOME}"
170-
command chmod go-w "${ZI_HOME}/${MOD_HOME}"
171-
fi
169+
ZPMOD_PROFILE() {
170+
_zpmod_sh=""
171+
case "$0" in
172+
*/*)
173+
_script_dir="$(cd "$(dirname "$0")" 2>/dev/null && pwd)" || _script_dir=""
174+
;;
175+
*)
176+
_script_dir=""
177+
;;
178+
esac
172179

173-
printf '%s\n' "${col_pname}== Downloading ZPMOD module to ${ZI_HOME}/${MOD_HOME}"
174-
if test -d "${ZI_HOME}/${MOD_HOME}/.git"; then
175-
cd "${ZI_HOME}/${MOD_HOME}" || return
176-
git pull -q origin main
180+
if [ -n "${_script_dir}" ] && [ -f "${_script_dir}/install_zpmod.sh" ]; then
181+
_zpmod_sh="${_script_dir}/install_zpmod.sh"
177182
else
178-
cd "${ZI_HOME}" || return
179-
git clone -q https://github.com/z-shell/zpmod.git "${MOD_HOME}"
180-
fi
181-
printf '%s\n' "${col_pname}== Done"
182-
}
183-
184-
BUILD_ZPMOD() {
185-
if command -v zsh >/dev/null; then
186-
printf '%s\n' "${col_info2}-- Checkig version --${col_rst}"
187-
ZSH_CURRENT=$(zsh --version </dev/null | head -n1 | cut -d" " -f2,6- | tr -d '-')
188-
ZSH_REQUIRED="5.8.1"
189-
if expr "${ZSH_CURRENT}" \< "${ZSH_REQUIRED}" >/dev/null; then
190-
printf '%s\n' "${col_error}-- Zsh version 5.8.1 and above required --${col_rst}"
191-
exit 1
183+
_zpmod_sh="${WORKDIR}/install_zpmod.sh"
184+
_zpmod_url="https://raw.githubusercontent.com/z-shell/zi-src/main/lib/sh/install_zpmod.sh"
185+
if command -v curl >/dev/null 2>&1; then
186+
command curl -fsSL "${_zpmod_url}" -o "${_zpmod_sh}"
187+
elif command -v wget >/dev/null 2>&1; then
188+
command wget -qO "${_zpmod_sh}" "${_zpmod_url}"
192189
else
193-
printf '%s\n' "${col_info2}-- Zsh version ${ZSH_CURRENT} --${col_rst}"
194-
cd "${ZI_HOME}/${MOD_HOME}" || return
195-
printf '%s\n' "${col_pname}== Building module ZPMOD, running: a make clean, then ./configure and then make ==${col_rst}"
196-
printf '%s\n' "${col_pname}== The module sources are located at: ${ZI_HOME}/${MOD_HOME} ==${col_rst}"
197-
if test -f Makefile; then
198-
if [ "$1" = "--clean" ]; then
199-
printf '%s\n' "${col_info2}-- make distclean --${col_rst}"
200-
make -s distclean
201-
true
202-
else
203-
printf '%s\n' "${col_info2}-- make clean (pass --clean to invoke \`make distclean') --${col_rst}"
204-
make -s clean
205-
fi
206-
fi
207-
printf '%s\n' "${col_info2}-- Configuring --${col_rst}"
208-
if CPPFLAGS=-I/usr/local/include CFLAGS="-g -Wall -O3" LDFLAGS=-L/usr/local/lib ./configure --disable-gdbm --without-tcsetpgrp; then
209-
printf '%s\n' "${col_info2}-- Running make --${col_rst}"
210-
if make -s; then
211-
command cat <<-EOF
212-
▓▒░ Module has been built correctly.
213-
▓▒░ To load the module, add following 2 lines to .zshrc, at top:
214-
  module_path+=( "${ZI_HOME}/${MOD_HOME}/Src" )
215-
  zmodload zi/zpmod
216-
▓▒░ See 'zpmod -h' for more information.
217-
▓▒░ Run 'zpmod source-study' to see profile data,
218-
▓▒░ Guaranteed, automatic compilation of any sourced script.
219-
EOF
220-
else
221-
printf '%s\n' "${col_error}Module didn't build.${col_rst}. You can copy the error messages and submit"
222-
printf '%s\n' "error-report at: https://github.com/z-shell/zpmod/issues"
223-
fi
224-
fi
190+
printf '%s\n' "-- ERROR -- curl or wget is required to download install_zpmod.sh" >&2
191+
exit 1
225192
fi
226-
else
227-
printf '%s\n' "${col_error} Zsh is not installed. Please install zsh and try again.${col_rst}"
193+
if [ ! -s "${_zpmod_sh}" ]; then
194+
printf '%s\n' "-- ERROR -- failed to download install_zpmod.sh" >&2
195+
exit 1
196+
fi
197+
command chmod a+x "${_zpmod_sh}"
228198
fi
229-
}
230199

231-
ZPMOD_PROFILE() {
232-
col_pname=""
233-
col_error=""
234-
col_info=""
235-
col_info2=""
236-
col_rst=""
237-
238-
ZI_HOME="${ZI_HOME:-${ZDOTDIR:-${HOME}}/.zi}"
239-
MOD_HOME="${MOD_HOME:-zmodules}/zpmod"
240-
241-
printf '%s\n' "${col_info}Re-run this script to update (from Github) and rebuild the module.${col_rst}"
242-
printf '%s\n' "${col_info2}Press any key to continue, or Ctrl-C to exit.${col_rst}"
243-
read -r
244-
245-
SETUP_ZPMOD
246-
BUILD_ZPMOD "$@"
200+
exec sh "${_zpmod_sh}" "$@"
247201
}
248202

249203
CLOSE_PROFILE() {
@@ -273,6 +227,4 @@ EOF
273227
exit 0
274228
}
275229

276-
while true; do
277-
MAIN "${@}"
278-
done
230+
MAIN "${@}"

lib/sh/install_zpmod.sh

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,56 @@
11
#!/usr/bin/env sh
2+
# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
3+
# vim: ft=sh sw=2 ts=2 et
4+
5+
set -eu
6+
7+
WORKDIR="$(mktemp -d)" || exit 1
8+
trap 'rm -rf "${WORKDIR:?}"' EXIT INT TERM
9+
10+
# Returns 0 if version $1 >= version $2 (dot-separated integers)
11+
_zi_ver_ge() {
12+
_vga="$1" _vgb="$2"
13+
while [ -n "${_vga}${_vgb}" ]; do
14+
_af="${_vga%%.*}" _bf="${_vgb%%.*}"
15+
case "${_vga}" in *.*) _vga="${_vga#*.}" ;; *) _vga="" ;; esac
16+
case "${_vgb}" in *.*) _vgb="${_vgb#*.}" ;; *) _vgb="" ;; esac
17+
_af="${_af:-0}" _bf="${_bf:-0}"
18+
if [ "${_af}" -gt "${_bf}" ]; then return 0; fi
19+
if [ "${_af}" -lt "${_bf}" ]; then return 1; fi
20+
done
21+
return 0
22+
}
223

324
setup_environment() {
4-
if [ -z "${ZI_HOME}" ]; then
5-
if [ -d "${HOME}"/.zi ]; then
25+
if [ -z "${ZI_HOME-}" ]; then
26+
_xdg_zi="${XDG_DATA_HOME:-${HOME}/.local/share}/zi"
27+
if [ -d "${_xdg_zi}" ]; then
28+
ZI_HOME="${_xdg_zi}"
29+
elif [ -d "${HOME}/.zi" ]; then
630
ZI_HOME="${HOME}/.zi"
7-
elif [ -d "${ZDOTDIR}"/.zi ]; then
31+
elif [ -n "${ZDOTDIR-}" ] && [ -d "${ZDOTDIR}/.zi" ]; then
832
ZI_HOME="${ZDOTDIR}/.zi"
9-
elif [ -d "${XDG_DATA_HOME}"/.zi ]; then
10-
ZI_HOME="${XDG_DATA_HOME}/.zi"
1133
else
12-
ZI_HOME="${HOME}/.zi"
34+
ZI_HOME="${_xdg_zi}"
1335
fi
1436
fi
15-
if [ -z "${MOD_HOME}" ]; then
37+
if [ -z "${MOD_HOME-}" ]; then
1638
MOD_HOME="${ZI_HOME}/zmodules/zpmod"
1739
fi
1840
if ! test -d "${MOD_HOME}"; then
1941
mkdir -p "${MOD_HOME}"
20-
chmod g-rwX "${MOD_HOME}"
42+
chmod go-w "${MOD_HOME}"
2143
fi
2244
if [ ! -d "${MOD_HOME}" ]; then
2345
printf '%s\n' "${col_error}== Error: Failed to setup module directory ==${col_rst}"
24-
exit 255
46+
exit 1
2547
fi
2648
}
2749

2850
setup_zpmod_repository() {
2951
printf '%s\n' "${col_pname}== Downloading ZPMOD module to ${MOD_HOME}"
3052
if test -d "${MOD_HOME}/.git"; then
31-
cd "${MOD_HOME}" || exit 255
53+
cd "${MOD_HOME}" || exit 1
3254
git pull -q origin main
3355
else
3456
git clone --depth 10 -q https://github.com/z-shell/zpmod.git "${MOD_HOME}"
@@ -39,18 +61,19 @@ build_zpmod_module() {
3961
if command -v zsh >/dev/null; then
4062
printf '%s\n' "${col_info2}-- Checking version --${col_rst}"
4163
ZSH_CURRENT=$(zsh --version </dev/null | head -n1 | cut -d" " -f2,6- | tr -d '-')
42-
ZSH_REQUIRED="5.8"
43-
if expr "${ZSH_CURRENT}" \< "${ZSH_REQUIRED}" >/dev/null; then
44-
printf '%s\n' "${col_error}-- Zsh version 5.8.1 and above required --${col_rst}"
64+
ZSH_REQUIRED="5.8.1"
65+
# shellcheck disable=SC2310
66+
if ! _zi_ver_ge "${ZSH_CURRENT}" "${ZSH_REQUIRED}"; then
67+
printf '%s\n' "${col_error}-- Zsh version ${ZSH_REQUIRED} and above required --${col_rst}"
4568
exit 1
4669
else
4770
(
4871
printf '%s\n' "${col_info2}-- Zsh version ${ZSH_CURRENT} --${col_rst}"
49-
cd "${MOD_HOME}" || exit 255
72+
cd "${MOD_HOME}" || exit 1
5073
printf '%s\n' "${col_pname}== Building module ZPMOD, running: a make clean, then ./configure and then make ==${col_rst}"
5174
printf '%s\n' "${col_pname}== The module sources are located at: ${MOD_HOME} ==${col_rst}"
5275
if test -f Makefile; then
53-
if [ "$1" = "--clean" ]; then
76+
if [ "${1-}" = "--clean" ]; then
5477
printf '%s\n' "${col_info2}-- make distclean --${col_rst}"
5578
make distclean
5679
true
@@ -62,9 +85,10 @@ build_zpmod_module() {
6285

6386
INSTALL_PATH="/usr/local"
6487
export PATH="${INSTALL_PATH}"/bin:"${PATH}"
65-
export LD_LIBRARY_PATH="${INSTALL_PATH}"/lib:"${LD_LIBRARY_PATH}"
66-
export CFLAGS=-I"${INSTALL_PATH}"/include
67-
export CPPFLAGS="-I${INSTALL_PATH}/include" LDFLAGS="-L${INSTALL_PATH}/lib"
88+
export LD_LIBRARY_PATH="${INSTALL_PATH}/lib:${LD_LIBRARY_PATH-}"
89+
export CFLAGS="-I${INSTALL_PATH}/include"
90+
export CPPFLAGS="-I${INSTALL_PATH}/include"
91+
export LDFLAGS="-L${INSTALL_PATH}/lib"
6892
CFLAGS="-g -Wall -O3" ./configure --disable-gdbm --without-tcsetpgrp --quiet
6993

7094
printf '%s\n' "${col_info2}-- Running make --${col_rst}"
@@ -84,13 +108,13 @@ EOF
84108
else
85109
printf '%s\n' "${col_error}Module didn't build.${col_rst}. You can copy the error messages and submit"
86110
printf '%s\n' "error-report at: https://github.com/z-shell/zpmod/issues"
87-
exit 255
111+
exit 1
88112
fi
89113
)
90114
fi
91115
else
92116
printf '%s\n' "${col_error} Zsh is not installed. Please install zsh and try again.${col_rst}"
93-
exit 255
117+
exit 1
94118
fi
95119
}
96120

@@ -106,6 +130,4 @@ MAIN() {
106130
exit 0
107131
}
108132

109-
while true; do
110-
MAIN "${@}"
111-
done
133+
MAIN "${@}"

0 commit comments

Comments
 (0)