installer: stop newest_matching_file from dying on SIGPIPE
ci/woodpecker/pr/ci Pipeline is pending approval
ci/woodpecker/pr/ci Pipeline is pending approval
newest_matching_file() piped `ls -1t` into `head -1`. Under `set -o pipefail` head closes the pipe after the first line, ls dies on SIGPIPE, and the function returns 141 having printed nothing. Its callers assign it at top level under `set -e`, so that 141 aborts the install. It takes roughly 1600 matching names to fill the pipe buffer, which is why this has sat unnoticed: with two or three files the old code is correct. Measured on origin/next with 5001 matches, the function returns 141 and prints nothing; with this change it returns rc=0 and the right filename. Two of the four callers are the "find the newest .mosaic-bak-* backup" lookup, which is the path a restore leans on. Reading the listing into an array through process substitution has no pipeline, so there is nothing for pipefail to catch. This also clears the one remaining violation `scripts/pipefail-early-exit.test.mjs` reports against tools/install.sh -- that test lives on main, not on next, so it starts failing the moment main is merged into next for the 0.0.50 integration. tools/install-newest-matching-file.test.sh pins it, including the large-population case that is the whole point. Red on origin/next (rc=141), green here. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01WYgWocp36goy8hj2ui6ps1
This commit is contained in:
co-authored by
Claude Opus 5
parent
cb2bf4e4a4
commit
06c714ddf3
+9
-1
@@ -169,8 +169,16 @@ newest_matching_file() {
|
||||
matches=("$dir"/$pattern)
|
||||
shopt -u nullglob
|
||||
[[ "${#matches[@]}" -gt 0 ]] || return 0
|
||||
# Read the whole listing and take the first entry, rather than piping into
|
||||
# `head -1`. Under `set -o pipefail`, head closes the pipe after one line, ls
|
||||
# dies on SIGPIPE, and the function returns 141 -- so on the day the directory
|
||||
# holds enough files to fill a pipe buffer, finding the newest one starts
|
||||
# failing the install. Process substitution has no pipeline to fail.
|
||||
local -a sorted=()
|
||||
# shellcheck disable=SC2012 # Need portable mtime sorting across Linux/macOS.
|
||||
ls -1t "${matches[@]}" 2>/dev/null | head -1
|
||||
mapfile -t sorted < <(ls -1t "${matches[@]}" 2>/dev/null)
|
||||
[[ "${#sorted[@]}" -gt 0 ]] || return 0
|
||||
printf '%s\n' "${sorted[0]}"
|
||||
}
|
||||
|
||||
# ─── uninstall path ───────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user