From 981cb1582ece95dfad9d6c53d34a601f6b25391f Mon Sep 17 00:00:00 2001 From: Vladislav Doster Date: Thu, 2 Jul 2026 06:45:42 -0500 Subject: [PATCH] fix(install): treat non-archive single file gracefully in ziextract. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change `ziextract` when no extractor case matches and no explicit type was passed (-z $ext), file is treated as plain single file with info message `'' is not an archive — keeping it as a plain file.` plus chmod a+x. The existing exec-bit collection then picks it up, sets REPLY for --move, prints normal success. Error message retained for explicit bogus types (ziextract file bogus-type). One iteration mid-verify: dropped -- from chmod — BSD/macOS chmod rejects it (chmod: --: No such file or directory). Why it broke: commit 1334994f (PR #771) made +x detection archive-exec-bit-only. Bare gh-r binaries arrive over HTTP with 644 and no extension => no extractor, no exec bit → error branch. Pre-#771, file(1) detection covered this case. Tests (tests/ices.zunit): two new — plain-file success path (asserts no error, message present, file executable) and bogus-explicit-type error retention. Suite 16/16, including #771's ziextract-permissions. Regression-validated: plain-file test fails 15/16 with fix stashed. Signed-off-by: Vladislav Doster --- tests/ices.zunit | 21 +++++++++++++++++++++ zinit-install.zsh | 11 +++++++++++ 2 files changed, 32 insertions(+) diff --git a/tests/ices.zunit b/tests/ices.zunit index 4d8c9ba6..258594bf 100755 --- a/tests/ices.zunit +++ b/tests/ices.zunit @@ -82,6 +82,27 @@ assert $output contains 'ERROR' assert $output contains "doesn't exist" } +@test 'ziextract plain single file (not an archive)' { + # A bare gh-r-style release binary: no "unrecognized archive" error, + # the file is kept as-is and marked executable. + local workdir=$(mktemp -d) + printf '#!/bin/sh\necho jq\n' > "$workdir/jq-macos-arm64" + _zi_extract_plain() { cd "$workdir" && ziextract jq-macos-arm64 } + run _zi_extract_plain + assert $state equals 0 + assert $output does_not_contain "didn't recognize archive type" + assert $output contains 'not an archive' + assert "$workdir/jq-macos-arm64" is_executable + rm -rf "$workdir" +} +@test 'ziextract still errors on unrecognized explicit type' { + local workdir=$(mktemp -d) + printf 'plain text\n' > "$workdir/somefile" + _zi_extract_bogus() { cd "$workdir" && ziextract somefile bogus-type } + run _zi_extract_bogus + assert $output contains "didn't recognize archive type" + rm -rf "$workdir" +} @test 'ziextract plain (no flattening)' { # extract'' → ziextract with no flags: directory structure is preserved local workdir=$(mktemp -d) diff --git a/zinit-install.zsh b/zinit-install.zsh index 5299a2f8..2796b47d 100644 --- a/zinit-install.zsh +++ b/zinit-install.zsh @@ -1754,6 +1754,17 @@ ziextract() { unfunction -- →zinit-extract →zinit-check } else { integer warning=1 + # Not an archive and no explicit type claimed — treat as a plain single + # file (e.g. a bare gh-r release binary). HTTP downloads carry no exec + # bit, so mark the file executable and let the execs collection below + # pick it up and report success. + if [[ -z $ext ]] { + warning=0 + (( !OPTS[opt_-q,--quiet] )) && \ + +zi-log "{info}[{pre}ziextract{info}]{rst}" \ + "\`{file}${file}{rst}' is not an archive — keeping it as a plain file." + command chmod a+x "$file" + } } unfunction -- .zinit-extract-wrapper