diff --git a/build/kernel-archive.sh b/build/kernel-archive.sh index eee9e9a..e5fa495 100755 --- a/build/kernel-archive.sh +++ b/build/kernel-archive.sh @@ -201,7 +201,10 @@ for entry in ${todo[@]+"${todo[@]}"}; do built="${PKGDIR}/${PACKAGE}/${PACKAGE#*/}-${version}-1.gpkg.tar" [[ -f ${built} ]] || die "建置完成但没有 -1 产物:${built}" - inner=$(tar -tf "${built}" | head -n1 | cut -d/ -f1) + # sed consumes the whole listing. head would close the pipe after the first + # line, tar would take SIGPIPE, and pipefail turns that into 141 with no + # message: the run died right after building, before publishing. + inner=$(tar -tf "${built}" | sed -n '1{s|/.*||;p;}') [[ ${inner} == "${PACKAGE#*/}-${version}-1" ]] || die "${version} 包内目录是 ${inner},不是 -1,${PACKAGE#*/}-bin 无法安装" diff --git a/tests/test-kernel-archive-integrity.sh b/tests/test-kernel-archive-integrity.sh index 2cd8157..0b743fa 100755 --- a/tests/test-kernel-archive-integrity.sh +++ b/tests/test-kernel-archive-integrity.sh @@ -13,6 +13,12 @@ mkdir -p "${WORK}/bin" "${WORK}/overlay" "${WORK}/tree" \ REAL_PYTHON=$(command -v python3) NAME=gentoo-cjk-kernel-7.1.7-1.amd64.gpkg.tar printf 'cjk\n' > "${WORK}/metadata/metadata/USE" +# Enough entries that `tar -tf | head -n1` reliably takes SIGPIPE. A real gpkg +# lists tens of thousands of paths; a two-entry fixture hid that for weeks. +mkdir -p "${WORK}/outer/gentoo-cjk-kernel-7.1.7-1/image" +for i in $(seq 1 3000); do + : > "${WORK}/outer/gentoo-cjk-kernel-7.1.7-1/image/f${i}" +done tar -C "${WORK}/metadata" -cf - metadata | zstd -q -o "${WORK}/metadata.tar.zst" cp "${WORK}/metadata.tar.zst" \ "${WORK}/outer/gentoo-cjk-kernel-7.1.7-1/metadata.tar.zst" @@ -20,6 +26,11 @@ tar --mtime=@1 -C "${WORK}/outer" -cf "${WORK}/built-first.gpkg.tar" \ gentoo-cjk-kernel-7.1.7-1 tar --mtime=@2 -C "${WORK}/outer" -cf "${WORK}/built-second.gpkg.tar" \ gentoo-cjk-kernel-7.1.7-1 +mkdir -p "${WORK}/outer-wrong/gentoo-cjk-kernel-7.1.7-3" +cp "${WORK}/metadata.tar.zst" \ + "${WORK}/outer-wrong/gentoo-cjk-kernel-7.1.7-3/metadata.tar.zst" +tar --mtime=@1 -C "${WORK}/outer-wrong" -cf "${WORK}/wrong-inner.gpkg.tar" \ + gentoo-cjk-kernel-7.1.7-3 cp "${WORK}/built-first.gpkg.tar" "${WORK}/corrupt.gpkg.tar" printf X | dd of="${WORK}/corrupt.gpkg.tar" bs=1 seek=512 conv=notrunc status=none @@ -169,6 +180,21 @@ cmp "${TEST_BUILT}" "${WORK}/published/7.1/${NAME}" [[ ! -e ${WORK}/published/7.1/gentoo-cjk-kernel-7.1.7-1.gpkg.tar ]] echo " ✓ 发布成功后按发布名保留完全相同的位元组" +# The -bin ebuild resolves BINPKG=${P/-bin}-1 against the directory inside the +# gpkg. Renaming the file does not rename what is inside it, so an artifact with +# the right file name and the wrong inner directory has to be refused. +reset_case +TEST_BUILT="${WORK}/wrong-inner.gpkg.tar" +write_manifest "${NAME}" "${TEST_BUILT}" +if run_archive 1 >"${WORK}/inner.out" 2>&1; then + echo " ✗ 包内目录不是 -1 时应当失败" + exit 1 +fi +grep -q '不是 -1' "${WORK}/inner.out" +[[ ! -e ${WORK}/remote/archive/7.1/${NAME} ]] +[[ ! -e ${WORK}/published/7.1/${NAME} ]] +echo " ✓ 包内目录不是 -1 时不发布也不保留" + reset_case RSYNC_FAIL=upload if run_archive 1 >/dev/null 2>&1; then diff --git a/tests/test-shell-behaviour.sh b/tests/test-shell-behaviour.sh index ea78cb3..177e85e 100755 --- a/tests/test-shell-behaviour.sh +++ b/tests/test-shell-behaviour.sh @@ -707,10 +707,6 @@ ok "移除之后重建索引" \ ok "只认 build id 为 1 的产物" \ "$(grep -c '${version}-1.gpkg.tar"$' "${ROOT}/build/kernel-archive.sh")" "1" # shellcheck disable=SC2016 # we grep for the literal ${VAR}, not its value -ok "核对包内目录名" \ - "$(grep -c 'tar -tf "${built}" | head -n1' \ - "${ROOT}/build/kernel-archive.sh")" "1" -# shellcheck disable=SC2016 # we grep for the literal ${VAR}, not its value ok "发布名固定是 -1" \ "$(grep -c 'name="\${PACKAGE#\*/}-\${version}-1\.\${ARCH}\.gpkg\.tar"' \ "${ROOT}/build/kernel-archive.sh")" "2"