fix(portability): make test green on macOS, GNU-only idioms replaced

The suite and seven libs assumed a GNU userland: `cmd | grep -q` under
pipefail (grep exits at the first match, the producer takes SIGPIPE,
rc 141 → 15 false "merged into" FAILs in gitflow-test), `sed -i` with no
suffix, `wc -l` padding compared as a string, `stat -c`, `touch -d`,
`realpath -m` (gstack-links refusal never fired), bare `timeout` off the
sanitized PATH (design gate READY BUT UNVERIFIED), `grep -oP` (update-all
emptied the plugin list). Thirteen suites were red on this machine.

Portable forms on the native userland of both OS: producer captured out
of the pipeline, `sed -i.bak` in tests and a temp-sibling `sed_profile`
on the user dotfile, `tr -d ' '`, python3 perms, `touch -t`, a
`realpath -m` emulation that refuses `..`, perl `alarm` for the 15 s
bound, `sed -n` token extraction. Regression tests: gstack-links T4b,
doctrine-citers Alphabet/Alpha flip, profile-set-managed T18 (failing CLI
no longer aborts `set`), new portability-census suite over the tracked
shell files. Linux run deferred (see TODO).
This commit is contained in:
bchanot
2026-10-06 15:10:20 +02:00
parent 4258a092e8
commit 0efdff0d55
23 changed files with 255 additions and 78 deletions
+20 -1
View File
@@ -49,6 +49,25 @@ if ! declare -F info >/dev/null 2>&1; then
info() { echo -e "${BLUE}→${NC} $1"; }
fi
# _gstack_links_realpath_m <path> — prints <path> resolved through its
# nearest existing ancestor (BSD realpath has no -m). rc 1 + warning when
# the path holds a `..` component: it cannot be resolved lexically.
_gstack_links_realpath_m() {
local path="${1%/}" rest="" dir base
case "/$path/" in
*/../*) warn "refusing path with '..': $1" >&2; return 1 ;;
esac
dir="$path"
while [ -n "$dir" ] && [ ! -d "$dir" ]; do
base="${dir##*/}"
rest="/$base$rest"
case "$dir" in */*) dir="${dir%/*}" ;; *) dir=. ;; esac
done
[ -n "$dir" ] || dir=/
dir="$(CDPATH='' cd -P -- "$dir" && pwd -P)" || return 1
printf '%s%s\n' "${dir%/}" "$rest"
}
# _gstack_links_guard_dst <src> <dst> — removes a stale <dst> symlink
# (gstack ./setup plants `skills/gstack -> skills-external/gstack` when
# the dir is absent), refuses ever writing INTO <src> (dst resolving
@@ -61,7 +80,7 @@ _gstack_links_guard_dst() {
rm -f "$dst"
fi
real_src="$(realpath "$src")"
real_dst="$(realpath -m "$dst")"
real_dst="$(_gstack_links_realpath_m "$dst")" || return 1
case "$real_dst" in
"$real_src"/*|"$real_src")
warn "refusing to write into the gstack submodule: $dst" >&2