6 Commits

Author SHA1 Message Date
jiarung
9944231ff4 fix(file-lock,git-hooks): PID reuse detection, null-payload race, prerelease sort
Three independent fixes bundled here because they came from the same
review pass.

── 1. Record lock owner identity beyond PID (file-lock) ──────────────

Stale-lock detection used only isPidAlive(), but PIDs are reusable.
On systems with small PID namespaces (containers, rapid restarts) a
crashed writer's PID can be reassigned to an unrelated live process,
causing isStaleLock to return false and the lock to appear held
indefinitely.

Fix: record the process start time (field 22 from /proc/{pid}/stat)
alongside pid and createdAt.  On Linux, if the current holder's
startTime differs from the stored value the PID was recycled and the
lock is reclaimed immediately.  On other platforms startTime is omitted
and the existing createdAt age-check (a reused PID inherits the old
timestamp, exceeding staleMs) remains as the fallback.

── 2. Restore mtime fallback for null/unparseable payloads (file-lock) ─

The previous fix treated null payload as immediately stale.  But the
lock file is created (empty) by open('wx') before writeFile fills in
the JSON.  A live writer still in that window has an empty file; marking
it stale immediately allows a second process to steal the lock and both
to enter fn() concurrently.

Fix: when payload is null, fall back to the file's mtime.  A file
younger than staleMs may belong to a live writer and is left alone; a
file older than staleMs was definitely orphaned and is reclaimed.  A
new test asserts that a freshly-created empty lock (recent mtime) is NOT
treated as stale.

── 3. Strip prerelease suffix before printf '%05d' (resolve-node.sh) ──

When an nvm install has a prerelease directory name (e.g.
v22.0.0-rc.1/bin/node), splitting on '.' leaves _pa as '0-rc.1'.
printf '%05d' then fails because '0-rc.1' is not an integer, and
set -euo pipefail aborts the hook before lint/format can run — the
opposite of what the nvm fallback is meant to achieve.

Fix: strip the longest non-digit suffix from each component before
printf: '0-rc.1' → '0', '14' → '14' (no-op for normal releases).
Uses POSIX parameter expansion  so it works on both
GNU bash and macOS bash 3.x.
2026-03-15 07:46:31 +00:00
jiarung
d3971e77fd fix(git-hooks): replace GNU-only sort -V with portable zero-pad sort
sort -V is a GNU extension; BSD sort on macOS does not support it. When
node is absent from PATH and the nvm fallback runs, set -euo pipefail
causes the unsupported flag to abort the hook before lint/format can
run, blocking commits on macOS.

Replace the sort -V | tail -1 pipeline with a Bash for-loop that
zero-pads each semver component to five digits and emits a tab-delimited
key+path line. Plain sort + tail -1 + cut then selects the highest
semantic version — no GNU-only flags required.

Smoke-tested with v18 vs v22 paths; v22 is correctly selected on both
GNU and BSD sort.
2026-03-15 05:14:07 +00:00
jiarung
98822509a8 fix(git-hooks): pick newest nvm Node with version-aware sort
The previous loop used Bash glob expansion (lexicographic order) and
stopped at the first match, so environments with multiple Node installs
could select an older runtime (e.g. v18 before v22).

Extract the nvm resolution into a shared scripts/pre-commit/resolve-node.sh
that pipes `ls` output through `sort -V | tail -1` to select the
semantically newest version. Both pre-commit and run-node-tool.sh now
source the shared script, eliminating the duplicated logic.
2026-03-13 14:17:36 +00:00
jiarung
4ced2e0ef0 fix(git-hooks): resolve node binary for nvm environments
When git hooks run, the shell profile is not sourced so nvm-managed
Node installations are not in PATH. This caused 'node: command not
found' errors on every commit for users relying on nvm.

Add a PATH-extension fallback in both pre-commit and run-node-tool.sh
that walks ~/.nvm/versions/node/*/bin/node and prepends the first
found binary to PATH, mirroring how nvm itself resolves the runtime.
2026-03-13 08:59:53 +00:00
Peter Steinberger
c1655982d4 refactor: centralize pre-commit file filtering 2026-02-16 03:42:11 +01:00
Peter Steinberger
50f233d16d chore: stabilize prek hooks runner selection (#1720) (thanks @dguido) 2026-01-25 10:55:28 +00:00