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' "▓▒░ ${ZI_HOME}/${ZI_BIN_DIR_NAME} contains a .git directory but does not appear to be a zi repository." >&2 + printf '%s\n' "▓▒░ 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' "▓▒░ Updating (z-shell/zi) plugin manager at ${ZI_HOME}/${ZI_BIN_DIR_NAME}" 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' "▓▒░ ${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