Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion public/checksum.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
6de66efba021ebcf462e7672577d9f6876f13db55691f04e7009ff7e78d658b8 public/sh/install_zpmod.sh
18f6c23188eb88242a21b6490bce922d576e571b0c5a32f1b0921a098b882273 public/sh/install.sh
ef5ba08f64df01abbe752f6fbab13d231d863d03d41a71fe8eac85979b268de0 public/sh/install.sh
08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh
c979e39748d1d86ace17a61ff2b1bf6e1224a43291c25bf7fad985d1e9e11af1 public/zsh/init.zsh
53 changes: 51 additions & 2 deletions public/sh/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@

set -eu

WORKDIR="$(mktemp -d "${TMPDIR:-/tmp}/zi-install.XXXXXX")" || exit 1
trap 'rm -rf "${WORKDIR:?}"' EXIT INT TERM
# Preserve whether the caller selected either checkout component. The loader
# stays dynamically resolved unless an explicit value must survive startup.
ZI_HOME_EXPLICIT=0
[ -z "${ZI_HOME-}" ] || ZI_HOME_EXPLICIT=1
ZI_BIN_DIR_NAME_EXPLICIT=0
[ -z "${ZI_BIN_DIR_NAME-}" ] || ZI_BIN_DIR_NAME_EXPLICIT=1
ZOPT=""
AOPT=""
BOPT="main"
Expand Down Expand Up @@ -47,6 +51,25 @@ case "${BOPT}" in
;;
esac

case "${ZDOTDIR-}" in
"" | /*) ;;
*)
printf '%s\n' "-- ERROR -- ZDOTDIR must be an absolute path when set: ${ZDOTDIR}" >&2
exit 1
;;
esac

case "${ZI_HOME-}" in
"" | /*) ;;
*)
printf '%s\n' "-- ERROR -- ZI_HOME must be an absolute path when set: ${ZI_HOME}" >&2
exit 1
;;
esac

WORKDIR="$(mktemp -d "${TMPDIR:-/tmp}/zi-install.XXXXXX")" || exit 1
trap 'rm -rf "${WORKDIR:?}"' EXIT INT TERM

SCRIPT_DIR=""
LOCAL_INIT_ZSH=""
LOCAL_INSTALL_ZPMOD=""
Expand Down Expand Up @@ -109,6 +132,14 @@ is_absolute_path() {
esac
}

zsh_single_quote() {
# Single-quoted Zsh text is inert; represent an embedded quote by ending the
# quote, escaping one literal quote, and reopening it.
printf "'"
printf '%s' "$1" | command sed "s/'/'\\\\''/g"
printf "'"
}

zi_home_has_installation() {
[ -f "$1/bin/zi.zsh" ] ||
[ -d "$1/plugins" ] ||
Expand Down Expand Up @@ -173,6 +204,16 @@ if [ -z "${ZI_BIN_DIR_NAME-}" ]; then
ZI_BIN_DIR_NAME="bin"
fi

ZI_LOADER_PATHS_EXPLICIT=0
ZI_LOADER_HOME_TEXT=""
ZI_LOADER_BIN_TEXT=""
if [ "${AOPT}" = loader ] &&
{ [ "${ZI_HOME_EXPLICIT}" -eq 1 ] || [ "${ZI_BIN_DIR_NAME_EXPLICIT}" -eq 1 ]; }; then
ZI_LOADER_PATHS_EXPLICIT=1
ZI_LOADER_HOME_TEXT="$(zsh_single_quote "${ZI_HOME}")"
ZI_LOADER_BIN_TEXT="$(zsh_single_quote "${ZI_HOME}/${ZI_BIN_DIR_NAME}")"
fi

if ! test -d "${ZI_HOME}"; then
command mkdir -p "${ZI_HOME}"
command chmod 700 "${ZI_HOME}"
Expand Down Expand Up @@ -295,6 +336,14 @@ if [[ -n \${XDG_CONFIG_HOME:-} && \${XDG_CONFIG_HOME} == /* ]]; then
else
ZI_LOADER_CONFIG_HOME="\${HOME}/.config/zi"
fi
EOF
if [ "${ZI_LOADER_PATHS_EXPLICIT}" -eq 1 ]; then
command printf '%s\n' \
'typeset -gA ZI' \
"ZI[HOME_DIR]=${ZI_LOADER_HOME_TEXT}" \
"ZI[BIN_DIR]=${ZI_LOADER_BIN_TEXT}" >>"${THE_ZDOTDIR}/.zshrc"
fi
command cat <<-EOF >>"${THE_ZDOTDIR}/.zshrc"
if [[ -r "\${ZI_LOADER_CONFIG_HOME}/init.zsh" ]]; then
source "\${ZI_LOADER_CONFIG_HOME}/init.zsh" && zzinit
fi
Expand Down
158 changes: 158 additions & 0 deletions tests/installers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,160 @@ test_sync_init() {
pass "sync-init fixtures"
}

test_loader_default_paths_remain_dynamic() {
home="${TMP_ROOT}/loader-dynamic-home"
config="${TMP_ROOT}/loader-dynamic-config"
data="${TMP_ROOT}/loader-dynamic-data"
command mkdir -p "${home}" "${config}" "${data}"

HOME="${home}" \
ZDOTDIR="${home}" \
XDG_CONFIG_HOME="${config}" \
XDG_DATA_HOME="${data}" \
ZI_SRC_TEST_ROOT="${ROOT}" \
PATH="${FAKE_BIN}:${PATH}" \
sh "${ROOT}/public/sh/install.sh" -a loader >/dev/null

if grep -F 'ZI[HOME_DIR]=' "${home}/.zshrc" >/dev/null 2>&1; then
fail "default loader install pinned a dynamically resolved home"
fi
pass "default loader paths remain dynamically resolved"
}

test_loader_carries_explicit_paths() {
home="${TMP_ROOT}/loader-explicit-home"
config="${TMP_ROOT}/loader-explicit-config"
data="${TMP_ROOT}/loader-explicit-data"
explicit="${TMP_ROOT}/loader explicit's root"
bin_name="custom \$(touch pwned) ' bin"
runtime_work="${TMP_ROOT}/loader-runtime-work"
values_log="${TMP_ROOT}/loader-explicit-values"
command mkdir -p "${home}" "${config}" "${data}" "${runtime_work}"

HOME="${home}" \
ZDOTDIR="${home}" \
XDG_CONFIG_HOME="${config}" \
XDG_DATA_HOME="${data}" \
ZI_HOME="${explicit}" \
ZI_BIN_DIR_NAME="${bin_name}" \
ZI_SRC_TEST_ROOT="${ROOT}" \
PATH="${FAKE_BIN}:${PATH}" \
sh "${ROOT}/public/sh/install.sh" -a loader >/dev/null

[ -f "${explicit}/${bin_name}/zi.zsh" ] || fail "loader install did not use the explicit checkout path"
contains "${home}/.zshrc" 'typeset -gA ZI'

(
cd "${runtime_work}" || exit 1
HOME="${home}" \
XDG_CONFIG_HOME="${config}" \
XDG_DATA_HOME="${data}" \
zsh -f -c '
source "$1"
print -r -- "home:${ZI[HOME_DIR]}"
print -r -- "bin:${ZI[BIN_DIR]}"
print -r -- "layout:${ZI[HOME_LAYOUT]}"
' zsh "${home}/.zshrc"
) >"${values_log}"

contains "${values_log}" "home:${explicit}"
contains "${values_log}" "bin:${explicit}/${bin_name}"
contains "${values_log}" 'layout:explicit'
[ ! -e "${runtime_work}/pwned" ] || fail "explicit loader path executed generated Zsh"
[ ! -e "${data}/zi/bin/zi.zsh" ] || fail "loader startup cloned a second checkout"
pass "loader carries explicit home and bin paths into startup safely"
}

test_loader_carries_explicit_bin_name() {
home="${TMP_ROOT}/loader-bin-home"
config="${TMP_ROOT}/loader-bin-config"
data="${TMP_ROOT}/loader-bin-data"
bin_name="custom bin"
values_log="${TMP_ROOT}/loader-bin-values"
command mkdir -p "${home}" "${config}" "${data}"

HOME="${home}" \
ZDOTDIR="${home}" \
XDG_CONFIG_HOME="${config}" \
XDG_DATA_HOME="${data}" \
ZI_BIN_DIR_NAME="${bin_name}" \
ZI_SRC_TEST_ROOT="${ROOT}" \
PATH="${FAKE_BIN}:${PATH}" \
sh "${ROOT}/public/sh/install.sh" -a loader >/dev/null

HOME="${home}" \
XDG_CONFIG_HOME="${config}" \
XDG_DATA_HOME="${data}" \
zsh -f -c '
source "$1"
print -r -- "home:${ZI[HOME_DIR]}"
print -r -- "bin:${ZI[BIN_DIR]}"
' zsh "${home}/.zshrc" >"${values_log}"

contains "${values_log}" "home:${data}/zi"
contains "${values_log}" "bin:${data}/zi/${bin_name}"
[ ! -e "${data}/zi/bin/zi.zsh" ] || fail "custom bin startup cloned into the default bin"
pass "loader carries an explicit bin name with the resolved home"
}

test_relative_installer_paths_are_rejected() {
zdot_home="${TMP_ROOT}/relative-zdot-home"
zdot_config="${TMP_ROOT}/relative-zdot-config"
zdot_data="${TMP_ROOT}/relative-zdot-data"
zdot_work="${TMP_ROOT}/relative-zdot-work"
zdot_err="${TMP_ROOT}/relative-zdot-err"
command mkdir -p "${zdot_home}" "${zdot_work}"

set +e
(
cd "${zdot_work}" || exit 1
HOME="${zdot_home}" \
ZDOTDIR="relative-zdotdir" \
XDG_CONFIG_HOME="${zdot_config}" \
XDG_DATA_HOME="${zdot_data}" \
ZI_SRC_TEST_ROOT="${ROOT}" \
PATH="${FAKE_BIN}:${PATH}" \
sh "${ROOT}/public/sh/install.sh" -a loader >/dev/null 2>"${zdot_err}"
)
exit_code="$?"
set -e

[ "${exit_code}" -ne 0 ] || fail "install.sh accepted a relative ZDOTDIR"
contains "${zdot_err}" 'ZDOTDIR must be an absolute path when set: relative-zdotdir'
[ ! -e "${zdot_config}" ] || fail "relative ZDOTDIR rejection wrote loader configuration"
[ ! -e "${zdot_data}" ] || fail "relative ZDOTDIR rejection created a checkout"
[ ! -e "${zdot_work}/relative-zdotdir" ] || fail "relative ZDOTDIR rejection created the relative path"

zi_home="${TMP_ROOT}/relative-zi-home"
zi_config="${TMP_ROOT}/relative-zi-config"
zi_data="${TMP_ROOT}/relative-zi-data"
zi_work="${TMP_ROOT}/relative-zi-work"
zi_err="${TMP_ROOT}/relative-zi-err"
command mkdir -p "${zi_home}" "${zi_work}"

set +e
(
cd "${zi_work}" || exit 1
HOME="${zi_home}" \
ZDOTDIR="${zi_home}" \
XDG_CONFIG_HOME="${zi_config}" \
XDG_DATA_HOME="${zi_data}" \
ZI_HOME="relative-zi-root" \
ZI_SRC_TEST_ROOT="${ROOT}" \
PATH="${FAKE_BIN}:${PATH}" \
sh "${ROOT}/public/sh/install.sh" -a loader >/dev/null 2>"${zi_err}"
)
exit_code="$?"
set -e

[ "${exit_code}" -ne 0 ] || fail "install.sh accepted a relative ZI_HOME"
contains "${zi_err}" 'ZI_HOME must be an absolute path when set: relative-zi-root'
[ ! -e "${zi_config}" ] || fail "relative ZI_HOME rejection wrote loader configuration"
[ ! -e "${zi_data}" ] || fail "relative ZI_HOME rejection created a default checkout"
[ ! -e "${zi_work}/relative-zi-root" ] || fail "relative ZI_HOME rejection created the relative checkout"
pass "relative ZDOTDIR and ZI_HOME are rejected before persistent mutation"
}

test_success_line_reports_exact_path() {
home="${TMP_ROOT}/success-home"
data="${TMP_ROOT}/success-data"
Expand Down Expand Up @@ -945,6 +1099,10 @@ test_init_uses_private_tempdir
test_init_path_resolution
write_fake_tools
test_loader_install
test_loader_default_paths_remain_dynamic
test_loader_carries_explicit_paths
test_loader_carries_explicit_bin_name
test_relative_installer_paths_are_rejected
test_xdg_data_home_install
test_legacy_home_install
test_relative_xdg_fallback_install
Expand Down
Loading