package_contract_assemble_package builds a tree that is exactly the runtime manifest, and then every caller named the top-level entries again by hand to zip them. That second list has no authority and no way to stay in step: post-fs-data.sh was added to the manifest, the package contract, the installer and the release build, and the CI workflow's own copy still omitted it — so the published archive failed package_contract_validate_zip_names on a file the contract required. There is nothing to enumerate: the archive is the assembly root. The release build, the CI workflow and the three packaging fixtures now archive it whole, which removes the class of failure rather than the instance. The test helper's store-only fallback normalizes the ./ prefix `find` adds, so both implementations produce the same names. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
139 lines
4.6 KiB
Shell
139 lines
4.6 KiB
Shell
#!/bin/sh
|
|
|
|
# Test-only ZIP fixture writer. Android root-manager busybox provides unzip and
|
|
# crc32 but no zip applet. Store entries without compression when a host zip
|
|
# command is unavailable; installer tests care about exact package contents,
|
|
# not the compression method.
|
|
|
|
z2_test_zip_emit_le() {
|
|
z2_zip_value="$1"
|
|
z2_zip_bytes="$2"
|
|
while [ "$z2_zip_bytes" -gt 0 ]; do
|
|
z2_zip_byte=$((z2_zip_value % 256))
|
|
z2_zip_octal="$(printf '%03o' "$z2_zip_byte")"
|
|
printf "\\$z2_zip_octal"
|
|
z2_zip_value=$((z2_zip_value / 256))
|
|
z2_zip_bytes=$((z2_zip_bytes - 1))
|
|
done
|
|
}
|
|
|
|
z2_test_zip_crc32() {
|
|
if command -v crc32 >/dev/null 2>&1; then
|
|
crc32 "$1"
|
|
return
|
|
fi
|
|
if command -v busybox >/dev/null 2>&1; then
|
|
busybox crc32 "$1"
|
|
return
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
z2_test_create_store_zip() {
|
|
z2_zip_archive="$1"
|
|
shift
|
|
z2_zip_manifest="$z2_zip_archive.manifest.$$"
|
|
z2_zip_central="$z2_zip_archive.central.$$"
|
|
: > "$z2_zip_manifest" || return 1
|
|
: > "$z2_zip_central" || {
|
|
rm -f "$z2_zip_manifest"
|
|
return 1
|
|
}
|
|
for z2_zip_input in "$@"; do
|
|
if [ -f "$z2_zip_input" ] && [ ! -L "$z2_zip_input" ]; then
|
|
printf '%s\n' "$z2_zip_input"
|
|
elif [ -d "$z2_zip_input" ] && [ ! -L "$z2_zip_input" ]; then
|
|
find "$z2_zip_input" -type f ! -type l -print
|
|
else
|
|
rm -f "$z2_zip_manifest" "$z2_zip_central"
|
|
return 1
|
|
fi
|
|
# `find .` yields ./-prefixed paths while zip(1) does not, and the archive
|
|
# names have to match whichever implementation ran.
|
|
done | sed 's|^\./||' | LC_ALL=C sort > "$z2_zip_manifest" || {
|
|
rm -f "$z2_zip_manifest" "$z2_zip_central"
|
|
return 1
|
|
}
|
|
|
|
: > "$z2_zip_archive" || {
|
|
rm -f "$z2_zip_manifest" "$z2_zip_central"
|
|
return 1
|
|
}
|
|
z2_zip_offset=0
|
|
z2_zip_count=0
|
|
while IFS= read -r z2_zip_name || [ -n "$z2_zip_name" ]; do
|
|
[ -n "$z2_zip_name" ] || continue
|
|
z2_zip_size="$(wc -c < "$z2_zip_name")" || return 1
|
|
z2_zip_name_size="$(printf '%s' "$z2_zip_name" | wc -c)" || return 1
|
|
z2_zip_crc="$(z2_test_zip_crc32 "$z2_zip_name")" || return 1
|
|
z2_zip_crc="${z2_zip_crc%% *}"
|
|
case "$z2_zip_crc" in
|
|
""|*[!0-9A-Fa-f]*) return 1 ;;
|
|
esac
|
|
z2_zip_crc_value=$((0x$z2_zip_crc))
|
|
|
|
{
|
|
printf '\120\113\003\004'
|
|
z2_test_zip_emit_le 20 2
|
|
z2_test_zip_emit_le 2048 2
|
|
z2_test_zip_emit_le 0 2
|
|
z2_test_zip_emit_le 0 2
|
|
z2_test_zip_emit_le 0 2
|
|
z2_test_zip_emit_le "$z2_zip_crc_value" 4
|
|
z2_test_zip_emit_le "$z2_zip_size" 4
|
|
z2_test_zip_emit_le "$z2_zip_size" 4
|
|
z2_test_zip_emit_le "$z2_zip_name_size" 2
|
|
z2_test_zip_emit_le 0 2
|
|
printf '%s' "$z2_zip_name"
|
|
cat "$z2_zip_name"
|
|
} >> "$z2_zip_archive" || return 1
|
|
|
|
{
|
|
printf '\120\113\001\002'
|
|
z2_test_zip_emit_le 20 2
|
|
z2_test_zip_emit_le 20 2
|
|
z2_test_zip_emit_le 2048 2
|
|
z2_test_zip_emit_le 0 2
|
|
z2_test_zip_emit_le 0 2
|
|
z2_test_zip_emit_le 0 2
|
|
z2_test_zip_emit_le "$z2_zip_crc_value" 4
|
|
z2_test_zip_emit_le "$z2_zip_size" 4
|
|
z2_test_zip_emit_le "$z2_zip_size" 4
|
|
z2_test_zip_emit_le "$z2_zip_name_size" 2
|
|
z2_test_zip_emit_le 0 2
|
|
z2_test_zip_emit_le 0 2
|
|
z2_test_zip_emit_le 0 2
|
|
z2_test_zip_emit_le 0 2
|
|
z2_test_zip_emit_le 0 4
|
|
z2_test_zip_emit_le "$z2_zip_offset" 4
|
|
printf '%s' "$z2_zip_name"
|
|
} >> "$z2_zip_central" || return 1
|
|
|
|
z2_zip_offset=$((z2_zip_offset + 30 + z2_zip_name_size + z2_zip_size))
|
|
z2_zip_count=$((z2_zip_count + 1))
|
|
done < "$z2_zip_manifest"
|
|
|
|
z2_zip_central_size="$(wc -c < "$z2_zip_central")" || return 1
|
|
cat "$z2_zip_central" >> "$z2_zip_archive" || return 1
|
|
{
|
|
printf '\120\113\005\006'
|
|
z2_test_zip_emit_le 0 2
|
|
z2_test_zip_emit_le 0 2
|
|
z2_test_zip_emit_le "$z2_zip_count" 2
|
|
z2_test_zip_emit_le "$z2_zip_count" 2
|
|
z2_test_zip_emit_le "$z2_zip_central_size" 4
|
|
z2_test_zip_emit_le "$z2_zip_offset" 4
|
|
z2_test_zip_emit_le 0 2
|
|
} >> "$z2_zip_archive" || return 1
|
|
rm -f "$z2_zip_manifest" "$z2_zip_central"
|
|
}
|
|
|
|
z2_test_create_zip() {
|
|
z2_zip_archive="$1"
|
|
shift
|
|
if command -v zip >/dev/null 2>&1; then
|
|
zip -qr "$z2_zip_archive" "$@"
|
|
else
|
|
z2_test_create_store_zip "$z2_zip_archive" "$@"
|
|
fi
|
|
}
|