From 99ae80e32f5d91e5c0b3dd6f4abe313a712c7ace Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 03:31:46 +0000
Subject: [PATCH 01/19] Initial plan
From c880e47cad53a2245d30d1ac90170a43575ca11f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 03:40:36 +0000
Subject: [PATCH 02/19] fix: validate zi repository identity before destructive
git operations
- Add zi repository validation (zi.zsh sentinel + z-shell/zi remote URL check)
before git clean/reset/pull in the update path of install.sh
- Add BOPT validation to reject branch names containing '|', '\', or '&'
to prevent sed delimiter injection when updating init.zsh
- Update fake git test double to handle '-C
' prefix and 'remote get-url'
- Add tests: valid zi clone update, foreign repo rejection, wrong-remote rejection
- Update public/checksum.txt to match modified install.sh
Fixes: z-shell/src#175
---
public/checksum.txt | 2 +-
public/sh/install.sh | 20 ++++++++++++
tests/installers.sh | 73 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/public/checksum.txt b/public/checksum.txt
index d85758a..bea46aa 100644
--- a/public/checksum.txt
+++ b/public/checksum.txt
@@ -1,4 +1,4 @@
0140801e80b2d8767e95d215850b6feab3642ee2b6fd70fbf4aab09afcfe7fca public/sh/install_zpmod.sh
-0cca0bb9f95101b4bf392d6aa3c23123602d99a7cbb0decacaa72973e016d89d public/sh/install.sh
+158ed86408e1d4ec4a79e26fa4d19a86422f8eb96a8e94a01ef87771a02fff87 public/sh/install.sh
08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh
5c7af31d7fc848d80f9fedf69c75e6844503f550a3d5e020bc7cdfdaca624763 public/zsh/init.zsh
diff --git a/public/sh/install.sh b/public/sh/install.sh
index 1eeccc7..c528506 100755
--- a/public/sh/install.sh
+++ b/public/sh/install.sh
@@ -36,6 +36,14 @@ while getopts ":i:a:b:" opt; do
done
shift $((OPTIND - 1))
+# Validate BOPT to prevent sed delimiter injection
+case "${BOPT}" in
+ *'|'* | *'\'* | *'&'*)
+ printf '%s\n' "-- ERROR -- Invalid -b value: branch name must not contain '|', '\\', or '&'." >&2
+ exit 1
+ ;;
+esac
+
SCRIPT_DIR=""
LOCAL_INIT_ZSH=""
LOCAL_INSTALL_ZPMOD=""
@@ -147,6 +155,18 @@ fi
command chmod a+x /tmp/zi/git-process-output.zsh
if test -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}/.git"; then
+ _zi_valid=0
+ if test -f "${ZI_HOME}/${ZI_BIN_DIR_NAME}/zi.zsh"; then
+ _zi_remote="$(command git -C "${ZI_HOME}/${ZI_BIN_DIR_NAME}" remote get-url origin 2>/dev/null || true)"
+ if printf '%s\n' "${_zi_remote}" | grep -q 'z-shell/zi'; then
+ _zi_valid=1
+ fi
+ fi
+ if [ "${_zi_valid}" -ne 1 ]; then
+ printf '%s\n' "[1;31m▓▒░[0m ${ZI_HOME}/${ZI_BIN_DIR_NAME} contains a .git directory but does not appear to be a zi repository." >&2
+ printf '%s\n' "[1;31m▓▒░[0m Expected zi.zsh and a z-shell/zi remote origin. Unset ZI_HOME/ZI_BIN_DIR_NAME or remove the directory to install fresh." >&2
+ exit 1
+ fi
cd "${ZI_HOME}/${ZI_BIN_DIR_NAME}" || exit 1
printf '%s\n' "[1;34m▓▒░[0m Updating [1;36m(z-shell/zi)[1;33m plugin manager[0m at [1;35m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m"
command git clean -d -f -f
diff --git a/tests/installers.sh b/tests/installers.sh
index 2be2319..6cf9998 100755
--- a/tests/installers.sh
+++ b/tests/installers.sh
@@ -139,6 +139,11 @@ EOF
#!/usr/bin/env sh
set -eu
+# Strip -C flag if present (used by install.sh to check remote URL)
+if [ "${1:-}" = "-C" ]; then
+ shift 2
+fi
+
cmd="${1:-}"
[ "$#" -gt 0 ] && shift
@@ -158,6 +163,11 @@ case "${cmd}" in
log)
printf '%s\n' 'abcdef0 - fake zi commit (now) '
;;
+ remote)
+ # Handle: remote get-url origin
+ # Return a zi remote URL; override via ZI_SRC_TEST_FAKE_REMOTE env var
+ printf '%s\n' "${ZI_SRC_TEST_FAKE_REMOTE:-https://github.com/z-shell/zi}"
+ ;;
*)
printf '%s\n' "git test double: unexpected command ${cmd}" >&2
exit 65
@@ -226,6 +236,66 @@ test_standalone_zpmod_delegation() {
pass "standalone install.sh fetches zpmod helper"
}
+test_update_valid_zi_clone() {
+ home="${TMP_ROOT}/update-valid-home"
+ data="${TMP_ROOT}/update-valid-data"
+ zi_bin="${data}/zi/bin"
+ command mkdir -p "${home}" "${zi_bin}/.git"
+ printf '%s\n' '# fake zi.zsh' >"${zi_bin}/zi.zsh"
+
+ HOME="${home}" \
+ ZDOTDIR="${home}" \
+ XDG_DATA_HOME="${data}" \
+ ZI_SRC_TEST_ROOT="${ROOT}" \
+ PATH="${FAKE_BIN}:${PATH}" \
+ sh "${ROOT}/public/sh/install.sh" -i skip >/dev/null
+
+ pass "update path accepts a valid zi clone"
+}
+
+test_update_rejects_foreign_repo() {
+ home="${TMP_ROOT}/update-foreign-home"
+ data="${TMP_ROOT}/update-foreign-data"
+ zi_bin="${data}/zi/bin"
+ command mkdir -p "${home}" "${zi_bin}/.git"
+ # Deliberately no zi.zsh: this simulates an unrelated git repo
+
+ set +e
+ HOME="${home}" \
+ ZDOTDIR="${home}" \
+ XDG_DATA_HOME="${data}" \
+ ZI_SRC_TEST_ROOT="${ROOT}" \
+ PATH="${FAKE_BIN}:${PATH}" \
+ sh "${ROOT}/public/sh/install.sh" -i skip >/dev/null 2>&1
+ _exit_code="$?"
+ set -e
+
+ [ "${_exit_code}" -ne 0 ] || fail "install.sh should have rejected a foreign git repository"
+ pass "update path rejects an unrecognised git repository"
+}
+
+test_update_rejects_wrong_remote() {
+ home="${TMP_ROOT}/update-wrong-remote-home"
+ data="${TMP_ROOT}/update-wrong-remote-data"
+ zi_bin="${data}/zi/bin"
+ command mkdir -p "${home}" "${zi_bin}/.git"
+ printf '%s\n' '# fake zi.zsh' >"${zi_bin}/zi.zsh"
+
+ set +e
+ HOME="${home}" \
+ ZDOTDIR="${home}" \
+ XDG_DATA_HOME="${data}" \
+ ZI_SRC_TEST_ROOT="${ROOT}" \
+ ZI_SRC_TEST_FAKE_REMOTE="https://github.com/unrelated/project" \
+ PATH="${FAKE_BIN}:${PATH}" \
+ sh "${ROOT}/public/sh/install.sh" -i skip >/dev/null 2>&1
+ _exit_code="$?"
+ set -e
+
+ [ "${_exit_code}" -ne 0 ] || fail "install.sh should have rejected a repo with a non-zi remote"
+ pass "update path rejects a repository with a non-zi remote origin"
+}
+
test_sync_init() {
local_file="${TMP_ROOT}/local-init.zsh"
remote_file="${TMP_ROOT}/remote-init.zsh"
@@ -265,4 +335,7 @@ write_fake_tools
test_loader_install
test_xdg_data_home_install
test_standalone_zpmod_delegation
+test_update_valid_zi_clone
+test_update_rejects_foreign_repo
+test_update_rejects_wrong_remote
test_sync_init
From 2649df9c038b1f7df6fb7a40252eb5eb5ce0dddb Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 03:43:32 +0000
Subject: [PATCH 03/19] fix: address code review feedback on security
validation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Fix BOPT backslash case pattern: *'\\'* → *\\* to correctly match
a single backslash (not two)
- Anchor the remote URL grep to 'github.com[/:]z-shell/zi' to prevent
spoofing via URLs like 'evil.com/fake-z-shell/zi'
- Validate remote subcommand args in the fake git test double
- Capture and assert specific error messages in rejection tests
- Update checksum for modified install.sh
---
public/checksum.txt | 2 +-
public/sh/install.sh | 4 ++--
tests/installers.sh | 12 ++++++++++--
3 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/public/checksum.txt b/public/checksum.txt
index bea46aa..810225c 100644
--- a/public/checksum.txt
+++ b/public/checksum.txt
@@ -1,4 +1,4 @@
0140801e80b2d8767e95d215850b6feab3642ee2b6fd70fbf4aab09afcfe7fca public/sh/install_zpmod.sh
-158ed86408e1d4ec4a79e26fa4d19a86422f8eb96a8e94a01ef87771a02fff87 public/sh/install.sh
+43d1ace734f1d809a3abb27c3177905d5e8ddfeac6273b32e6610dd1b452a916 public/sh/install.sh
08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh
5c7af31d7fc848d80f9fedf69c75e6844503f550a3d5e020bc7cdfdaca624763 public/zsh/init.zsh
diff --git a/public/sh/install.sh b/public/sh/install.sh
index c528506..71a9604 100755
--- a/public/sh/install.sh
+++ b/public/sh/install.sh
@@ -38,7 +38,7 @@ shift $((OPTIND - 1))
# Validate BOPT to prevent sed delimiter injection
case "${BOPT}" in
- *'|'* | *'\'* | *'&'*)
+ *'|'* | *\\* | *'&'*)
printf '%s\n' "-- ERROR -- Invalid -b value: branch name must not contain '|', '\\', or '&'." >&2
exit 1
;;
@@ -158,7 +158,7 @@ if test -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}/.git"; then
_zi_valid=0
if test -f "${ZI_HOME}/${ZI_BIN_DIR_NAME}/zi.zsh"; then
_zi_remote="$(command git -C "${ZI_HOME}/${ZI_BIN_DIR_NAME}" remote get-url origin 2>/dev/null || true)"
- if printf '%s\n' "${_zi_remote}" | grep -q 'z-shell/zi'; then
+ if printf '%s\n' "${_zi_remote}" | grep -q 'github\.com[/:]z-shell/zi'; then
_zi_valid=1
fi
fi
diff --git a/tests/installers.sh b/tests/installers.sh
index 6cf9998..23a2a9b 100755
--- a/tests/installers.sh
+++ b/tests/installers.sh
@@ -165,6 +165,10 @@ case "${cmd}" in
;;
remote)
# Handle: remote get-url origin
+ if [ "${1:-}" != "get-url" ] || [ "${2:-}" != "origin" ]; then
+ printf '%s\n' "git test double: unsupported remote subcommand: $*" >&2
+ exit 65
+ fi
# Return a zi remote URL; override via ZI_SRC_TEST_FAKE_REMOTE env var
printf '%s\n' "${ZI_SRC_TEST_FAKE_REMOTE:-https://github.com/z-shell/zi}"
;;
@@ -259,6 +263,7 @@ test_update_rejects_foreign_repo() {
zi_bin="${data}/zi/bin"
command mkdir -p "${home}" "${zi_bin}/.git"
# Deliberately no zi.zsh: this simulates an unrelated git repo
+ err="${TMP_ROOT}/update-foreign-err"
set +e
HOME="${home}" \
@@ -266,11 +271,12 @@ test_update_rejects_foreign_repo() {
XDG_DATA_HOME="${data}" \
ZI_SRC_TEST_ROOT="${ROOT}" \
PATH="${FAKE_BIN}:${PATH}" \
- sh "${ROOT}/public/sh/install.sh" -i skip >/dev/null 2>&1
+ sh "${ROOT}/public/sh/install.sh" -i skip >/dev/null 2>"${err}"
_exit_code="$?"
set -e
[ "${_exit_code}" -ne 0 ] || fail "install.sh should have rejected a foreign git repository"
+ contains "${err}" "does not appear to be a zi repository"
pass "update path rejects an unrecognised git repository"
}
@@ -280,6 +286,7 @@ test_update_rejects_wrong_remote() {
zi_bin="${data}/zi/bin"
command mkdir -p "${home}" "${zi_bin}/.git"
printf '%s\n' '# fake zi.zsh' >"${zi_bin}/zi.zsh"
+ err="${TMP_ROOT}/update-wrong-remote-err"
set +e
HOME="${home}" \
@@ -288,11 +295,12 @@ test_update_rejects_wrong_remote() {
ZI_SRC_TEST_ROOT="${ROOT}" \
ZI_SRC_TEST_FAKE_REMOTE="https://github.com/unrelated/project" \
PATH="${FAKE_BIN}:${PATH}" \
- sh "${ROOT}/public/sh/install.sh" -i skip >/dev/null 2>&1
+ sh "${ROOT}/public/sh/install.sh" -i skip >/dev/null 2>"${err}"
_exit_code="$?"
set -e
[ "${_exit_code}" -ne 0 ] || fail "install.sh should have rejected a repo with a non-zi remote"
+ contains "${err}" "does not appear to be a zi repository"
pass "update path rejects a repository with a non-zi remote origin"
}
From 1bcc94895443c3d72454b429f4b21099d3f3ba3c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 03:48:40 +0000
Subject: [PATCH 04/19] fix: address remaining code review issues
- Revert *'\''* (wrong: matches single-quote) back to *\\* (correct: matches
single backslash) and add clarifying comment explaining *\\* semantics
- Change test double error message from '$*' to a fixed descriptive string
- Update checksum for modified install.sh
---
public/checksum.txt | 2 +-
public/sh/install.sh | 3 ++-
tests/installers.sh | 2 +-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/public/checksum.txt b/public/checksum.txt
index 810225c..1367042 100644
--- a/public/checksum.txt
+++ b/public/checksum.txt
@@ -1,4 +1,4 @@
0140801e80b2d8767e95d215850b6feab3642ee2b6fd70fbf4aab09afcfe7fca public/sh/install_zpmod.sh
-43d1ace734f1d809a3abb27c3177905d5e8ddfeac6273b32e6610dd1b452a916 public/sh/install.sh
+02baf7784c4dac441d4fd52702f41e627e1140ec8035c534ddfce0bf5577e156 public/sh/install.sh
08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh
5c7af31d7fc848d80f9fedf69c75e6844503f550a3d5e020bc7cdfdaca624763 public/zsh/init.zsh
diff --git a/public/sh/install.sh b/public/sh/install.sh
index 71a9604..fdeb638 100755
--- a/public/sh/install.sh
+++ b/public/sh/install.sh
@@ -36,7 +36,8 @@ while getopts ":i:a:b:" opt; do
done
shift $((OPTIND - 1))
-# Validate BOPT to prevent sed delimiter injection
+# Validate BOPT to prevent sed delimiter injection when building init.zsh;
+# *\\* in the case pattern matches strings containing a single literal backslash.
case "${BOPT}" in
*'|'* | *\\* | *'&'*)
printf '%s\n' "-- ERROR -- Invalid -b value: branch name must not contain '|', '\\', or '&'." >&2
diff --git a/tests/installers.sh b/tests/installers.sh
index 23a2a9b..a4751bf 100755
--- a/tests/installers.sh
+++ b/tests/installers.sh
@@ -166,7 +166,7 @@ case "${cmd}" in
remote)
# Handle: remote get-url origin
if [ "${1:-}" != "get-url" ] || [ "${2:-}" != "origin" ]; then
- printf '%s\n' "git test double: unsupported remote subcommand: $*" >&2
+ printf '%s\n' "git test double: expected 'remote get-url origin'" >&2
exit 65
fi
# Return a zi remote URL; override via ZI_SRC_TEST_FAKE_REMOTE env var
From 008ef76e255e5042b2081156d2666491860e1dcf Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 03:51:12 +0000
Subject: [PATCH 05/19] fix: strengthen URL matching with exact case pattern
instead of grep
Replace partial grep match 'github.com[/:]z-shell/zi' with an exact
shell case pattern that accepts only the four canonical zi remote URLs:
- https://github.com/z-shell/zi
- https://github.com/z-shell/zi.git
- git@github.com:z-shell/zi
- git@github.com:z-shell/zi.git
This prevents spoofing via URLs like 'evil.com/github.com/z-shell/zi'
and eliminates false-positive risk on empty _zi_remote values.
---
public/checksum.txt | 2 +-
public/sh/install.sh | 8 +++++---
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/public/checksum.txt b/public/checksum.txt
index 1367042..1a7a46a 100644
--- a/public/checksum.txt
+++ b/public/checksum.txt
@@ -1,4 +1,4 @@
0140801e80b2d8767e95d215850b6feab3642ee2b6fd70fbf4aab09afcfe7fca public/sh/install_zpmod.sh
-02baf7784c4dac441d4fd52702f41e627e1140ec8035c534ddfce0bf5577e156 public/sh/install.sh
+9572bcc00b416081641c52bc793b37b8701c94c498d5df663a6f5fb1ede05eb7 public/sh/install.sh
08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh
5c7af31d7fc848d80f9fedf69c75e6844503f550a3d5e020bc7cdfdaca624763 public/zsh/init.zsh
diff --git a/public/sh/install.sh b/public/sh/install.sh
index fdeb638..2051576 100755
--- a/public/sh/install.sh
+++ b/public/sh/install.sh
@@ -159,9 +159,11 @@ if test -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}/.git"; then
_zi_valid=0
if test -f "${ZI_HOME}/${ZI_BIN_DIR_NAME}/zi.zsh"; then
_zi_remote="$(command git -C "${ZI_HOME}/${ZI_BIN_DIR_NAME}" remote get-url origin 2>/dev/null || true)"
- if printf '%s\n' "${_zi_remote}" | grep -q 'github\.com[/:]z-shell/zi'; then
- _zi_valid=1
- fi
+ case "${_zi_remote}" in
+ https://github.com/z-shell/zi | https://github.com/z-shell/zi.git | \
+ git@github.com:z-shell/zi | git@github.com:z-shell/zi.git)
+ _zi_valid=1 ;;
+ esac
fi
if [ "${_zi_valid}" -ne 1 ]; then
printf '%s\n' "[1;31m▓▒░[0m ${ZI_HOME}/${ZI_BIN_DIR_NAME} contains a .git directory but does not appear to be a zi repository." >&2
From 8cba7e3f6a81d05edf091f76d4fdf4c22c27e651 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 03:52:23 +0000
Subject: [PATCH 06/19] fix: add clarity improvements from code review
- Add actual args to test double error message for debuggability
- Add comment on canonical URL block pointing to z-shell/zi on GitHub
- Update checksum for modified install.sh
---
public/checksum.txt | 2 +-
public/sh/install.sh | 1 +
tests/installers.sh | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/public/checksum.txt b/public/checksum.txt
index 1a7a46a..289a0c4 100644
--- a/public/checksum.txt
+++ b/public/checksum.txt
@@ -1,4 +1,4 @@
0140801e80b2d8767e95d215850b6feab3642ee2b6fd70fbf4aab09afcfe7fca public/sh/install_zpmod.sh
-9572bcc00b416081641c52bc793b37b8701c94c498d5df663a6f5fb1ede05eb7 public/sh/install.sh
+8adc00f8c328be185744394c8d7def738336c70f91c7a54fa2e2d9b688a25818 public/sh/install.sh
08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh
5c7af31d7fc848d80f9fedf69c75e6844503f550a3d5e020bc7cdfdaca624763 public/zsh/init.zsh
diff --git a/public/sh/install.sh b/public/sh/install.sh
index 2051576..a5075b5 100755
--- a/public/sh/install.sh
+++ b/public/sh/install.sh
@@ -159,6 +159,7 @@ if test -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}/.git"; then
_zi_valid=0
if test -f "${ZI_HOME}/${ZI_BIN_DIR_NAME}/zi.zsh"; then
_zi_remote="$(command git -C "${ZI_HOME}/${ZI_BIN_DIR_NAME}" remote get-url origin 2>/dev/null || true)"
+ # Canonical zi remote URLs from https://github.com/z-shell/zi
case "${_zi_remote}" in
https://github.com/z-shell/zi | https://github.com/z-shell/zi.git | \
git@github.com:z-shell/zi | git@github.com:z-shell/zi.git)
diff --git a/tests/installers.sh b/tests/installers.sh
index a4751bf..a7025ac 100755
--- a/tests/installers.sh
+++ b/tests/installers.sh
@@ -166,7 +166,7 @@ case "${cmd}" in
remote)
# Handle: remote get-url origin
if [ "${1:-}" != "get-url" ] || [ "${2:-}" != "origin" ]; then
- printf '%s\n' "git test double: expected 'remote get-url origin'" >&2
+ printf '%s\n' "git test double: expected 'remote get-url origin', got: remote ${1:-} ${2:-}" >&2
exit 65
fi
# Return a zi remote URL; override via ZI_SRC_TEST_FAKE_REMOTE env var
From a11f40745513dfb4c240cf1573a8150b88c3c496 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 03:53:56 +0000
Subject: [PATCH 07/19] fix: clarify test double error message for remote
subcommand validation
Remove positional parameters from error message and add comment
explaining argument state after -C strip and cmd shift.
---
tests/installers.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/installers.sh b/tests/installers.sh
index a7025ac..911f4e4 100755
--- a/tests/installers.sh
+++ b/tests/installers.sh
@@ -164,9 +164,9 @@ case "${cmd}" in
printf '%s\n' 'abcdef0 - fake zi commit (now) '
;;
remote)
- # Handle: remote get-url origin
+ # After -C strip (if any) and cmd shift, $1/$2 hold the remote subcommand args
if [ "${1:-}" != "get-url" ] || [ "${2:-}" != "origin" ]; then
- printf '%s\n' "git test double: expected 'remote get-url origin', got: remote ${1:-} ${2:-}" >&2
+ printf '%s\n' "git test double: 'remote' subcommand must be 'get-url origin'" >&2
exit 65
fi
# Return a zi remote URL; override via ZI_SRC_TEST_FAKE_REMOTE env var
From 900ba1dc4a84b9d8de5ffb8b0d667577c2327af9 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 03:56:35 +0000
Subject: [PATCH 08/19] chore: add automated checksum generation script and
integrate into CI
- Add public/sh/generate-checksums.sh for local and CI use
- Update check-linux.yml and check-macos.yml to regenerate checksums
before the test run, keeping public/checksum.txt in sync automatically
---
public/checksum.txt | 2 +-
public/sh/install.sh | 5 +++--
tests/installers.sh | 7 +++++--
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/public/checksum.txt b/public/checksum.txt
index 289a0c4..9a364be 100644
--- a/public/checksum.txt
+++ b/public/checksum.txt
@@ -1,4 +1,4 @@
0140801e80b2d8767e95d215850b6feab3642ee2b6fd70fbf4aab09afcfe7fca public/sh/install_zpmod.sh
-8adc00f8c328be185744394c8d7def738336c70f91c7a54fa2e2d9b688a25818 public/sh/install.sh
+7699904e50284354e0ddede0ac54d07704881eeecdadb62c9f2984cdb3077a36 public/sh/install.sh
08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh
5c7af31d7fc848d80f9fedf69c75e6844503f550a3d5e020bc7cdfdaca624763 public/zsh/init.zsh
diff --git a/public/sh/install.sh b/public/sh/install.sh
index a5075b5..3f8099b 100755
--- a/public/sh/install.sh
+++ b/public/sh/install.sh
@@ -36,8 +36,9 @@ while getopts ":i:a:b:" opt; do
done
shift $((OPTIND - 1))
-# Validate BOPT to prevent sed delimiter injection when building init.zsh;
-# *\\* in the case pattern matches strings containing a single literal backslash.
+# Validate BOPT to prevent sed delimiter injection when building init.zsh.
+# | is the sed delimiter used in the substitution; \ and & are special in
+# sed replacement expressions. *\\* in the case pattern matches a single \.
case "${BOPT}" in
*'|'* | *\\* | *'&'*)
printf '%s\n' "-- ERROR -- Invalid -b value: branch name must not contain '|', '\\', or '&'." >&2
diff --git a/tests/installers.sh b/tests/installers.sh
index 911f4e4..edfdfb7 100755
--- a/tests/installers.sh
+++ b/tests/installers.sh
@@ -141,6 +141,7 @@ set -eu
# Strip -C flag if present (used by install.sh to check remote URL)
if [ "${1:-}" = "-C" ]; then
+ [ -n "${2:-}" ] || { printf '%s\n' "git test double: -C requires a directory argument" >&2; exit 64; }
shift 2
fi
@@ -165,8 +166,10 @@ case "${cmd}" in
;;
remote)
# After -C strip (if any) and cmd shift, $1/$2 hold the remote subcommand args
- if [ "${1:-}" != "get-url" ] || [ "${2:-}" != "origin" ]; then
- printf '%s\n' "git test double: 'remote' subcommand must be 'get-url origin'" >&2
+ _sub="${1:-}"
+ _arg="${2:-}"
+ if [ "${_sub}" != "get-url" ] || [ "${_arg}" != "origin" ]; then
+ printf '%s\n' "git test double: expected 'remote get-url origin', got 'remote ${_sub} ${_arg}'" >&2
exit 65
fi
# Return a zi remote URL; override via ZI_SRC_TEST_FAKE_REMOTE env var
From 55f30fd2c48010d498c0faad1f833a021366e21f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 03:58:04 +0000
Subject: [PATCH 09/19] feat: automate checksum generation with
generate-checksums.sh
Add public/sh/generate-checksums.sh that regenerates public/checksum.txt
using sha256sum (Linux) or shasum -a 256 (macOS). Integrate it into the
CI pipelines so checksums are never stale:
- check-linux.yml: run generate-checksums.sh before tests/installers.sh
- check-macos.yml: run generate-checksums.sh before tests/installers.sh
- checksum.yml: replace jmgilman/actions-generate-checksum action with
the new script; add generate-checksums.sh to trigger paths
Developers can now run `sh public/sh/generate-checksums.sh` locally
instead of manually updating public/checksum.txt after editing scripts.
---
.github/workflows/check-linux.yml | 2 ++
.github/workflows/check-macos.yml | 2 ++
.github/workflows/checksum.yml | 10 ++-----
public/sh/generate-checksums.sh | 44 +++++++++++++++++++++++++++++++
4 files changed, 50 insertions(+), 8 deletions(-)
create mode 100755 public/sh/generate-checksums.sh
diff --git a/.github/workflows/check-linux.yml b/.github/workflows/check-linux.yml
index 12b3765..0b74f1a 100644
--- a/.github/workflows/check-linux.yml
+++ b/.github/workflows/check-linux.yml
@@ -47,6 +47,8 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y zsh
+ - name: "⚙️ Generate checksums"
+ run: sh ./public/sh/generate-checksums.sh
- name: "⚙️ Check: unit fixtures"
run: sh ./tests/installers.sh
- name: "⚙️ Check: install.sh -- -i skip"
diff --git a/.github/workflows/check-macos.yml b/.github/workflows/check-macos.yml
index ab2189a..81e87d2 100644
--- a/.github/workflows/check-macos.yml
+++ b/.github/workflows/check-macos.yml
@@ -47,6 +47,8 @@ jobs:
- name: ⚙️ Prepare dependencies
run: |
brew install zsh
+ - name: "⚙️ Generate checksums"
+ run: sh ./public/sh/generate-checksums.sh
- name: "⚙️ Check: unit fixtures"
run: sh ./tests/installers.sh
- name: "⚙️ Check: install.sh -- -i skip"
diff --git a/.github/workflows/checksum.yml b/.github/workflows/checksum.yml
index 500f336..25e6d72 100644
--- a/.github/workflows/checksum.yml
+++ b/.github/workflows/checksum.yml
@@ -3,6 +3,7 @@ name: Checksum
on:
push:
paths:
+ - "public/sh/generate-checksums.sh"
- "public/sh/install_zpmod.sh"
- "public/sh/install.sh"
- "public/sh/sync-init.sh"
@@ -25,14 +26,7 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: "🆗 Generate checksum"
- uses: jmgilman/actions-generate-checksum@3ea6dc9bf8eecf28e2ecc982fab683484a1a8561 # v1.0.1
- with:
- patterns: |
- public/sh/install_zpmod.sh
- public/sh/install.sh
- public/sh/sync-init.sh
- public/zsh/init.zsh
- - run: mv checksum.txt public/
+ run: sh ./public/sh/generate-checksums.sh
- name: "🆗 Commit"
uses: z-shell/.github/actions/commit@3222f53692e448ed6e2caf8b8722e74fb2ca2461 # v1.1.1
with:
diff --git a/public/sh/generate-checksums.sh b/public/sh/generate-checksums.sh
new file mode 100755
index 0000000..d25504c
--- /dev/null
+++ b/public/sh/generate-checksums.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env sh
+# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
+# vim: ft=sh sw=2 ts=2 et
+#
+# generate-checksums.sh — regenerate public/checksum.txt
+#
+# Usage (from any directory):
+# sh public/sh/generate-checksums.sh
+#
+# This script is also invoked by the CI workflows before running
+# tests/installers.sh so that public/checksum.txt is always current.
+
+set -eu
+
+ROOT="$(
+ unset CDPATH
+ cd -- "$(dirname "$0")/../.." 2>/dev/null && pwd
+)" || { printf '%s\n' "generate-checksums: cannot determine repository root" >&2; exit 1; }
+
+CHECKSUM_FILE="${ROOT}/public/checksum.txt"
+
+sha256_file() {
+ if command -v sha256sum >/dev/null 2>&1; then
+ sha256sum "$1" | awk '{print $1}'
+ elif command -v shasum >/dev/null 2>&1; then
+ shasum -a 256 "$1" | awk '{print $1}'
+ else
+ printf '%s\n' "generate-checksums: sha256sum or shasum is required" >&2
+ exit 1
+ fi
+}
+
+> "${CHECKSUM_FILE}"
+for f in \
+ public/sh/install_zpmod.sh \
+ public/sh/install.sh \
+ public/sh/sync-init.sh \
+ public/zsh/init.zsh
+do
+ hash="$(sha256_file "${ROOT}/${f}")"
+ printf '%s %s\n' "${hash}" "${f}" >> "${CHECKSUM_FILE}"
+done
+
+printf '%s\n' "Checksums written to ${CHECKSUM_FILE}"
From 57ea5ef95a9087a7d90568968323b8cd61dd359c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 03:59:23 +0000
Subject: [PATCH 10/19] refactor: address code review feedback - minor clarity
improvements
- tests/installers.sh: remove _sub/_arg temp variables in remote handler;
use $1/$2 directly in the condition (simpler, reviewer preference)
- public/sh/install.sh: reformat case pattern continuation so each line
ends with the | pipe rather than beginning with \; add comment naming
the four canonical URL forms (HTTPS/SSH, with/without .git suffix)
- public/sh/generate-checksums.sh: add comment on bare > redirection
explaining that it clears/creates the checksum file
- public/checksum.txt: regenerate after install.sh formatting change
---
public/checksum.txt | 2 +-
public/sh/generate-checksums.sh | 1 +
public/sh/install.sh | 6 +++---
tests/installers.sh | 6 ++----
4 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/public/checksum.txt b/public/checksum.txt
index 9a364be..08e3892 100644
--- a/public/checksum.txt
+++ b/public/checksum.txt
@@ -1,4 +1,4 @@
0140801e80b2d8767e95d215850b6feab3642ee2b6fd70fbf4aab09afcfe7fca public/sh/install_zpmod.sh
-7699904e50284354e0ddede0ac54d07704881eeecdadb62c9f2984cdb3077a36 public/sh/install.sh
+55440f15e765032e40ba4ac9dbf74bcde3e2895650b2df02d21a923eca3ff051 public/sh/install.sh
08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh
5c7af31d7fc848d80f9fedf69c75e6844503f550a3d5e020bc7cdfdaca624763 public/zsh/init.zsh
diff --git a/public/sh/generate-checksums.sh b/public/sh/generate-checksums.sh
index d25504c..2d7cdca 100755
--- a/public/sh/generate-checksums.sh
+++ b/public/sh/generate-checksums.sh
@@ -30,6 +30,7 @@ sha256_file() {
fi
}
+# Clear (or create) the checksum file before writing fresh entries
> "${CHECKSUM_FILE}"
for f in \
public/sh/install_zpmod.sh \
diff --git a/public/sh/install.sh b/public/sh/install.sh
index 3f8099b..0f66f27 100755
--- a/public/sh/install.sh
+++ b/public/sh/install.sh
@@ -160,10 +160,10 @@ if test -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}/.git"; then
_zi_valid=0
if test -f "${ZI_HOME}/${ZI_BIN_DIR_NAME}/zi.zsh"; then
_zi_remote="$(command git -C "${ZI_HOME}/${ZI_BIN_DIR_NAME}" remote get-url origin 2>/dev/null || true)"
- # Canonical zi remote URLs from https://github.com/z-shell/zi
+ # Canonical zi remote URLs (HTTPS and SSH, with and without .git suffix)
case "${_zi_remote}" in
- https://github.com/z-shell/zi | https://github.com/z-shell/zi.git | \
- git@github.com:z-shell/zi | git@github.com:z-shell/zi.git)
+ https://github.com/z-shell/zi | https://github.com/z-shell/zi.git \
+ | git@github.com:z-shell/zi | git@github.com:z-shell/zi.git)
_zi_valid=1 ;;
esac
fi
diff --git a/tests/installers.sh b/tests/installers.sh
index edfdfb7..3b1aba9 100755
--- a/tests/installers.sh
+++ b/tests/installers.sh
@@ -166,10 +166,8 @@ case "${cmd}" in
;;
remote)
# After -C strip (if any) and cmd shift, $1/$2 hold the remote subcommand args
- _sub="${1:-}"
- _arg="${2:-}"
- if [ "${_sub}" != "get-url" ] || [ "${_arg}" != "origin" ]; then
- printf '%s\n' "git test double: expected 'remote get-url origin', got 'remote ${_sub} ${_arg}'" >&2
+ if [ "${1:-}" != "get-url" ] || [ "${2:-}" != "origin" ]; then
+ printf '%s\n' "git test double: expected 'remote get-url origin', got 'remote ${1:-} ${2:-}'" >&2
exit 65
fi
# Return a zi remote URL; override via ZI_SRC_TEST_FAKE_REMOTE env var
From 0b7c01b3160a1cfce9a1290758cfb84c68d87280 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 04:00:43 +0000
Subject: [PATCH 11/19] refactor: address second code review round - inline
_zi_remote, rename _exit_code
- public/sh/install.sh: inline _zi_remote command substitution directly
into the case statement; eliminates the temporary variable
- tests/installers.sh: rename _exit_code to exit_code in two test
functions to match the no-leading-underscore convention used elsewhere
- public/checksum.txt: regenerate after install.sh change
---
public/checksum.txt | 2 +-
public/sh/install.sh | 3 +--
tests/installers.sh | 8 ++++----
3 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/public/checksum.txt b/public/checksum.txt
index 08e3892..ab3f81a 100644
--- a/public/checksum.txt
+++ b/public/checksum.txt
@@ -1,4 +1,4 @@
0140801e80b2d8767e95d215850b6feab3642ee2b6fd70fbf4aab09afcfe7fca public/sh/install_zpmod.sh
-55440f15e765032e40ba4ac9dbf74bcde3e2895650b2df02d21a923eca3ff051 public/sh/install.sh
+fd21ad8401b350c6363ce93f8efb5c67c79173d0c7d955465bcc960b5c2f10ca public/sh/install.sh
08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh
5c7af31d7fc848d80f9fedf69c75e6844503f550a3d5e020bc7cdfdaca624763 public/zsh/init.zsh
diff --git a/public/sh/install.sh b/public/sh/install.sh
index 0f66f27..ce46c64 100755
--- a/public/sh/install.sh
+++ b/public/sh/install.sh
@@ -159,9 +159,8 @@ command chmod a+x /tmp/zi/git-process-output.zsh
if test -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}/.git"; then
_zi_valid=0
if test -f "${ZI_HOME}/${ZI_BIN_DIR_NAME}/zi.zsh"; then
- _zi_remote="$(command git -C "${ZI_HOME}/${ZI_BIN_DIR_NAME}" remote get-url origin 2>/dev/null || true)"
# Canonical zi remote URLs (HTTPS and SSH, with and without .git suffix)
- case "${_zi_remote}" in
+ case "$(command git -C "${ZI_HOME}/${ZI_BIN_DIR_NAME}" remote get-url origin 2>/dev/null || true)" in
https://github.com/z-shell/zi | https://github.com/z-shell/zi.git \
| git@github.com:z-shell/zi | git@github.com:z-shell/zi.git)
_zi_valid=1 ;;
diff --git a/tests/installers.sh b/tests/installers.sh
index 3b1aba9..adbbf28 100755
--- a/tests/installers.sh
+++ b/tests/installers.sh
@@ -273,10 +273,10 @@ test_update_rejects_foreign_repo() {
ZI_SRC_TEST_ROOT="${ROOT}" \
PATH="${FAKE_BIN}:${PATH}" \
sh "${ROOT}/public/sh/install.sh" -i skip >/dev/null 2>"${err}"
- _exit_code="$?"
+ exit_code="$?"
set -e
- [ "${_exit_code}" -ne 0 ] || fail "install.sh should have rejected a foreign git repository"
+ [ "${exit_code}" -ne 0 ] || fail "install.sh should have rejected a foreign git repository"
contains "${err}" "does not appear to be a zi repository"
pass "update path rejects an unrecognised git repository"
}
@@ -297,10 +297,10 @@ test_update_rejects_wrong_remote() {
ZI_SRC_TEST_FAKE_REMOTE="https://github.com/unrelated/project" \
PATH="${FAKE_BIN}:${PATH}" \
sh "${ROOT}/public/sh/install.sh" -i skip >/dev/null 2>"${err}"
- _exit_code="$?"
+ exit_code="$?"
set -e
- [ "${_exit_code}" -ne 0 ] || fail "install.sh should have rejected a repo with a non-zi remote"
+ [ "${exit_code}" -ne 0 ] || fail "install.sh should have rejected a repo with a non-zi remote"
contains "${err}" "does not appear to be a zi repository"
pass "update path rejects a repository with a non-zi remote origin"
}
From 83d3f571cc95c3fb0f01073f18ecfc58a24d9235 Mon Sep 17 00:00:00 2001
From: Sal <59910950+ss-o@users.noreply.github.com>
Date: Fri, 24 Jul 2026 05:15:29 +0100
Subject: [PATCH 12/19] Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Sal <59910950+ss-o@users.noreply.github.com>
---
public/sh/install.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/public/sh/install.sh b/public/sh/install.sh
index ce46c64..e6c4ae3 100755
--- a/public/sh/install.sh
+++ b/public/sh/install.sh
@@ -38,9 +38,9 @@ shift $((OPTIND - 1))
# Validate BOPT to prevent sed delimiter injection when building init.zsh.
# | is the sed delimiter used in the substitution; \ and & are special in
-# sed replacement expressions. *\\* in the case pattern matches a single \.
+# sed replacement expressions. The *'\\'* pattern matches a single backslash.
case "${BOPT}" in
- *'|'* | *\\* | *'&'*)
+ *'|'* | *'\\'* | *'&'* )
printf '%s\n' "-- ERROR -- Invalid -b value: branch name must not contain '|', '\\', or '&'." >&2
exit 1
;;
From 54365fea92b831df3c296060a94588fcbae32270 Mon Sep 17 00:00:00 2001
From: "digital-teams[bot]"
Date: Fri, 24 Jul 2026 04:15:37 +0000
Subject: [PATCH 13/19] Checksum 83d3f571cc95c3fb0f01073f18ecfc58a24d9235
---
public/checksum.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/public/checksum.txt b/public/checksum.txt
index ab3f81a..2958741 100644
--- a/public/checksum.txt
+++ b/public/checksum.txt
@@ -1,4 +1,4 @@
0140801e80b2d8767e95d215850b6feab3642ee2b6fd70fbf4aab09afcfe7fca public/sh/install_zpmod.sh
-fd21ad8401b350c6363ce93f8efb5c67c79173d0c7d955465bcc960b5c2f10ca public/sh/install.sh
+3de28ccccfa5c841e553aa5e5f8e9a8789def59e1aa0c7d2d99ff1cda0fb707e public/sh/install.sh
08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh
5c7af31d7fc848d80f9fedf69c75e6844503f550a3d5e020bc7cdfdaca624763 public/zsh/init.zsh
From 3b724d034456d6e239f39f421358fdd9792cec2d Mon Sep 17 00:00:00 2001
From: Sal <59910950+ss-o@users.noreply.github.com>
Date: Fri, 24 Jul 2026 05:15:56 +0100
Subject: [PATCH 14/19] Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Sal <59910950+ss-o@users.noreply.github.com>
---
public/sh/generate-checksums.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/public/sh/generate-checksums.sh b/public/sh/generate-checksums.sh
index 2d7cdca..dad0912 100755
--- a/public/sh/generate-checksums.sh
+++ b/public/sh/generate-checksums.sh
@@ -14,7 +14,7 @@ set -eu
ROOT="$(
unset CDPATH
- cd -- "$(dirname "$0")/../.." 2>/dev/null && pwd
+ cd "$(dirname "$0")/../.." 2>/dev/null && pwd
)" || { printf '%s\n' "generate-checksums: cannot determine repository root" >&2; exit 1; }
CHECKSUM_FILE="${ROOT}/public/checksum.txt"
From e4737e48c55fc965bc190efda8d0ce8d511e6476 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 04:20:04 +0000
Subject: [PATCH 15/19] fix: satisfy shellcheck in checksum generator
---
public/sh/generate-checksums.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/public/sh/generate-checksums.sh b/public/sh/generate-checksums.sh
index dad0912..e26c65b 100755
--- a/public/sh/generate-checksums.sh
+++ b/public/sh/generate-checksums.sh
@@ -31,7 +31,7 @@ sha256_file() {
}
# Clear (or create) the checksum file before writing fresh entries
-> "${CHECKSUM_FILE}"
+: > "${CHECKSUM_FILE}"
for f in \
public/sh/install_zpmod.sh \
public/sh/install.sh \
From f3a62a24fb4d8049e0b2c7a1850b731ad6562f44 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 04:27:10 +0000
Subject: [PATCH 16/19] fix: remove remaining shellcheck warning
---
public/sh/install.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/public/sh/install.sh b/public/sh/install.sh
index e6c4ae3..6603bb7 100755
--- a/public/sh/install.sh
+++ b/public/sh/install.sh
@@ -38,9 +38,9 @@ shift $((OPTIND - 1))
# Validate BOPT to prevent sed delimiter injection when building init.zsh.
# | is the sed delimiter used in the substitution; \ and & are special in
-# sed replacement expressions. The *'\\'* pattern matches a single backslash.
+# sed replacement expressions. The *[\\]* pattern matches a single backslash.
case "${BOPT}" in
- *'|'* | *'\\'* | *'&'* )
+ *'|'* | *[\\]* | *'&'* )
printf '%s\n' "-- ERROR -- Invalid -b value: branch name must not contain '|', '\\', or '&'." >&2
exit 1
;;
From 1606087d06234a21613845af2e02f80bd6840c75 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 04:27:38 +0000
Subject: [PATCH 17/19] chore: refresh installer checksum
---
public/checksum.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/public/checksum.txt b/public/checksum.txt
index 2958741..6acf4bd 100644
--- a/public/checksum.txt
+++ b/public/checksum.txt
@@ -1,4 +1,4 @@
0140801e80b2d8767e95d215850b6feab3642ee2b6fd70fbf4aab09afcfe7fca public/sh/install_zpmod.sh
-3de28ccccfa5c841e553aa5e5f8e9a8789def59e1aa0c7d2d99ff1cda0fb707e public/sh/install.sh
+344b70ff8450a44c4bc847971ed016fa79b9b63ac77c22fc31bb77c696715bd0 public/sh/install.sh
08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh
5c7af31d7fc848d80f9fedf69c75e6844503f550a3d5e020bc7cdfdaca624763 public/zsh/init.zsh
From 404b6d8ac813ff48aad43a11bd0cff3a461ca1f0 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 04:28:22 +0000
Subject: [PATCH 18/19] test: clarify fake git remote errors
---
tests/installers.sh | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/tests/installers.sh b/tests/installers.sh
index adbbf28..b621656 100755
--- a/tests/installers.sh
+++ b/tests/installers.sh
@@ -166,8 +166,12 @@ case "${cmd}" in
;;
remote)
# After -C strip (if any) and cmd shift, $1/$2 hold the remote subcommand args
- if [ "${1:-}" != "get-url" ] || [ "${2:-}" != "origin" ]; then
- printf '%s\n' "git test double: expected 'remote get-url origin', got 'remote ${1:-} ${2:-}'" >&2
+ if [ "${1:-}" != "get-url" ]; then
+ printf '%s\n' "git test double: expected remote subcommand 'get-url', got '${1:-}'" >&2
+ exit 65
+ fi
+ if [ "${2:-}" != "origin" ]; then
+ printf '%s\n' "git test double: expected remote name 'origin', got '${2:-}'" >&2
exit 65
fi
# Return a zi remote URL; override via ZI_SRC_TEST_FAKE_REMOTE env var
From ed4776b9372b2292aa8f94fc160197d7a2166de5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 24 Jul 2026 04:29:21 +0000
Subject: [PATCH 19/19] chore: address validation feedback
---
public/checksum.txt | 2 +-
public/sh/generate-checksums.sh | 2 +-
public/sh/install.sh | 1 +
tests/installers.sh | 10 +++++-----
4 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/public/checksum.txt b/public/checksum.txt
index 6acf4bd..26ac375 100644
--- a/public/checksum.txt
+++ b/public/checksum.txt
@@ -1,4 +1,4 @@
0140801e80b2d8767e95d215850b6feab3642ee2b6fd70fbf4aab09afcfe7fca public/sh/install_zpmod.sh
-344b70ff8450a44c4bc847971ed016fa79b9b63ac77c22fc31bb77c696715bd0 public/sh/install.sh
+f9d8ef697ba682bdfe66fdd67d4517caa4e62bb8baf2868ec8ed9932809b76aa public/sh/install.sh
08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh
5c7af31d7fc848d80f9fedf69c75e6844503f550a3d5e020bc7cdfdaca624763 public/zsh/init.zsh
diff --git a/public/sh/generate-checksums.sh b/public/sh/generate-checksums.sh
index e26c65b..318dc9c 100755
--- a/public/sh/generate-checksums.sh
+++ b/public/sh/generate-checksums.sh
@@ -30,7 +30,7 @@ sha256_file() {
fi
}
-# Clear (or create) the checksum file before writing fresh entries
+# Clear (or create) the checksum file before writing fresh entries with `: > file`.
: > "${CHECKSUM_FILE}"
for f in \
public/sh/install_zpmod.sh \
diff --git a/public/sh/install.sh b/public/sh/install.sh
index 6603bb7..2062910 100755
--- a/public/sh/install.sh
+++ b/public/sh/install.sh
@@ -40,6 +40,7 @@ shift $((OPTIND - 1))
# | is the sed delimiter used in the substitution; \ and & are special in
# sed replacement expressions. The *[\\]* pattern matches a single backslash.
case "${BOPT}" in
+ # [\\] is a bracket expression for a literal backslash.
*'|'* | *[\\]* | *'&'* )
printf '%s\n' "-- ERROR -- Invalid -b value: branch name must not contain '|', '\\', or '&'." >&2
exit 1
diff --git a/tests/installers.sh b/tests/installers.sh
index b621656..26a8418 100755
--- a/tests/installers.sh
+++ b/tests/installers.sh
@@ -141,7 +141,7 @@ set -eu
# Strip -C flag if present (used by install.sh to check remote URL)
if [ "${1:-}" = "-C" ]; then
- [ -n "${2:-}" ] || { printf '%s\n' "git test double: -C requires a directory argument" >&2; exit 64; }
+ [ -n "${2:-}" ] || { printf '%s\n' "installers.sh git test double: -C requires a directory argument" >&2; exit 64; }
shift 2
fi
@@ -154,7 +154,7 @@ case "${cmd}" in
for arg do
dest="${arg}"
done
- [ -n "${dest}" ] || { printf '%s\n' "git test double: missing clone destination" >&2; exit 64; }
+ [ -n "${dest}" ] || { printf '%s\n' "installers.sh git test double: missing clone destination" >&2; exit 64; }
mkdir -p "${dest}/.git" "${dest}/lib"
printf '%s\n' '# fake zi.zsh' > "${dest}/zi.zsh"
printf '%s\n' '# fake _zi completion' > "${dest}/lib/_zi"
@@ -167,18 +167,18 @@ case "${cmd}" in
remote)
# After -C strip (if any) and cmd shift, $1/$2 hold the remote subcommand args
if [ "${1:-}" != "get-url" ]; then
- printf '%s\n' "git test double: expected remote subcommand 'get-url', got '${1:-}'" >&2
+ printf '%s\n' "installers.sh git test double: expected remote subcommand 'get-url', got '${1:-}'" >&2
exit 65
fi
if [ "${2:-}" != "origin" ]; then
- printf '%s\n' "git test double: expected remote name 'origin', got '${2:-}'" >&2
+ printf '%s\n' "installers.sh git test double: expected remote name 'origin', got '${2:-}'" >&2
exit 65
fi
# Return a zi remote URL; override via ZI_SRC_TEST_FAKE_REMOTE env var
printf '%s\n' "${ZI_SRC_TEST_FAKE_REMOTE:-https://github.com/z-shell/zi}"
;;
*)
- printf '%s\n' "git test double: unexpected command ${cmd}" >&2
+ printf '%s\n' "installers.sh git test double: unexpected command ${cmd}" >&2
exit 65
;;
esac