zdharma-continuum.zinit/tests/ices.zunit
Vladislav Doster 981cb1582e fix(install): treat non-archive single file gracefully in ziextract.
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
`'<file>' 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 <mvdoster@gmail.com>
2026-07-02 06:58:41 -05:00

193 lines
7.4 KiB
Bash
Executable file

#!/usr/bin/env zunit
@setup {
ZPLUGINS=$ZINIT[PLUGINS_DIR]
function _zunit_assert_not_executable(){
local pathname=$1 filepath
# If filepath is relative, prepend the test directory
if [[ "${pathname:0:1}" != "/" ]]; then
filepath="$testdir/${pathname}"
else
filepath="$pathname"
fi
[[ ! -x "$filepath" ]] && return 0
echo "'$pathname' is executable but should not be"
exit 1
}
function _zunit_assert_not_exists(){
local file_path=$1
if [[ "${file_path:0:1}" != "/" ]]; then # relative path - prepend the test directory
filepath="${testdir}/${file_path}"
fi
[[ ! -e "$file_path" ]] && return 0
exit "found '${file_path}'"
}
}
@test 'mv' {
run zinit as"null" id-as"test/mv" mv"readme.md -> mv.md" for zdharma-continuum/null
assert $state equals 0
assert "$ZPLUGINS/test---mv/mv.md" is_file
assert "$ZPLUGINS/test---mv/mv.md" is_readable
assert "$ZPLUGINS/test---mv/readme.md" not_exists
}
@test 'cp' {
run zinit as"null" id-as"test/cp" cp"readme.md -> cp.md" for zdharma-continuum/null
assert $state equals 0
assert "$ZPLUGINS/test---cp/cp.md" is_file
assert "$ZPLUGINS/test---cp/cp.md" is_readable
assert "$ZPLUGINS/test---cp/readme.md" is_file
}
@test 'atclone' {
run zinit as"null" id-as"test/atclone" atclone"mv readme.md atclone.md" for zdharma-continuum/null
assert $state equals 0
assert "$ZPLUGINS/test---atclone/atclone.md" is_file
assert "$ZPLUGINS/test---atclone/atclone.md" is_readable
assert "$ZPLUGINS/test---atclone/readme.md" not_exists
}
@test 'make' {
run zinit as"null" id-as"test/make" atclone"printf 'all:\n\ttouch whatever\n' > Makefile" make"all" for zdharma-continuum/null
assert $state equals 0
assert "$ZPLUGINS/test---make/whatever" is_file
}
@test 'completions' {
run zinit as"null" id-as"test/completions" atclone"touch _whatever" completions for zdharma-continuum/null
assert $state equals 0
assert "$ZPLUGINS/test---completions/_whatever" is_file
assert "$ZINIT[COMPLETIONS_DIR]/_whatever" is_file
}
@test 'completions-overwrite' {
# if both are given, the completions wins
run zinit as"null" id-as"test/completions-overwrite" atclone"touch _whatever2" nocompletions completions for zdharma-continuum/null
assert $state equals 0
assert "$ZPLUGINS/test---completions-overwrite/_whatever2" is_file
assert "$ZINIT[COMPLETIONS_DIR]/_whatever2" is_file
}
@test 'completions-ignored' {
# only the _valid file should be installed as a completion
run zinit as"null" id-as"test/ignored_completions" atclone"touch __init__.py _valid" completions for zdharma-continuum/null
assert $state equals 0
assert "$ZPLUGINS/test---ignored_completions/_valid" is_file
assert "$ZPLUGINS/test---ignored_completions/__init__.py" is_file
assert "$ZINIT[COMPLETIONS_DIR]/_valid" is_file
COMPS=( "$ZINIT[COMPLETIONS_DIR]"/_* )
assert __init__.py is_not_value_in $COMPS
}
@test 'ziextract error on missing file' {
run ziextract /tmp/zi-nonexistent-file.zip
assert $state equals 1
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)
mkdir "$workdir/subdir"
printf 'hello\n' > "$workdir/subdir/file1.txt"
( cd "$workdir" && zip -qr test.zip subdir/ )
( cd "$workdir" && ziextract test.zip )
assert "$workdir/subdir/file1.txt" is_file
assert "$workdir/file1.txt" not_exists
rm -rf "$workdir"
}
@test 'ziextract --move (flatten one level)' {
# extract'!' → ziextract --move: outer/file.txt → file.txt at root
local workdir=$(mktemp -d)
mkdir "$workdir/outer"
printf 'hello\n' > "$workdir/outer/file1.txt"
printf 'world\n' > "$workdir/outer/file2.txt"
( cd "$workdir" && zip -qr test.zip outer/ )
( cd "$workdir" && ziextract test.zip --move )
assert "$workdir/file1.txt" is_file
assert "$workdir/file2.txt" is_file
assert "$workdir/outer" not_exists
rm -rf "$workdir"
}
@test 'ziextract --move2 (flatten two levels)' {
# extract'!!' → ziextract --move --move2: outer/inner/file.txt → file.txt at root
local workdir=$(mktemp -d)
mkdir -p "$workdir/outer/inner"
printf 'hello\n' > "$workdir/outer/inner/file1.txt"
( cd "$workdir" && zip -qr test.zip outer/ )
( cd "$workdir" && ziextract test.zip --move --move2 )
assert "$workdir/file1.txt" is_file
assert "$workdir/outer" not_exists
rm -rf "$workdir"
}
@test 'ziextract deletes archive by default' {
local workdir=$(mktemp -d)
( cd "$workdir" && printf 'hello\n' > file1.txt && zip -q test.zip file1.txt && rm file1.txt )
( cd "$workdir" && ziextract test.zip )
assert "$workdir/file1.txt" is_file
assert "$workdir/test.zip" not_exists
rm -rf "$workdir"
}
@test 'ziextract --norm keeps archive after extraction' {
# extract'-' → ziextract --norm: archive is preserved after extraction
local workdir=$(mktemp -d)
( cd "$workdir" && printf 'hello\n' > file1.txt && zip -q test.zip file1.txt && rm file1.txt )
( cd "$workdir" && ziextract test.zip --norm )
assert "$workdir/file1.txt" is_file
assert "$workdir/test.zip" is_file
rm -rf "$workdir"
}
@test 'ziextract-permissions' {
# Build a zip with known permissions, call ziextract directly, and verify
# that only files with +x in the archive come out executable.
local srcdir workdir
srcdir=$(mktemp -d)
workdir=$(mktemp -d)
# run_me.sh: +x in archive, has shebang → must be executable
printf '#!/bin/sh\necho run\n' > "$srcdir/run_me.sh"
chmod +x "$srcdir/run_me.sh"
# also_run.py: no +x in archive, has shebang → must NOT be executable (shebang alone is not enough)
printf '#!/usr/bin/env python3\nprint("hi")\n' > "$srcdir/also_run.py"
# library.py: no +x, no shebang → must NOT be executable
printf 'def foo(): pass\n' > "$srcdir/library.py"
# pre_marked.sh: +x in archive, no shebang → must be executable (archive bit)
printf 'echo pre\n' > "$srcdir/pre_marked.sh"
chmod +x "$srcdir/pre_marked.sh"
# Build zip preserving permissions, then extract via ziextract
( cd "$srcdir" && zip -q "$workdir/test.zip" run_me.sh also_run.py library.py pre_marked.sh )
(( ${+functions[ziextract]} )) || builtin source "${ZINIT[BIN_DIR]}/zinit-install.zsh"
( builtin cd "$workdir" && ziextract test.zip )
assert "$workdir/run_me.sh" is_executable
assert "$workdir/pre_marked.sh" is_executable
assert "$workdir/also_run.py" not_executable
assert "$workdir/library.py" not_executable
rm -rf "$srcdir" "$workdir"
}
# vim:ft=zsh:sw=2:sts=2:et:foldmarker=\ {,}:foldmethod=marker