From 84c7b32b82487b178d81c38c13b5ade86cfad19c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 22 Aug 2026 23:46:11 +1000 Subject: [PATCH] build: hash stamps with git hash-object, not shasum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit stamp_digest was the one place still shelling out to shasum. decision_key already carries the reason not to: git hash-object rather than shasum/sha1sum/openssl: it is the one hashing tool guaranteed to be present, since desvio cannot run at all without git. worktree_fingerprint follows that rule too. This applies it to the third site. shasum ships with macOS Perl but is absent on stock Arch and on minimal container images, and its absence is silent rather than loud: the command substitution yields an empty digest, a missing stamp file also reads as the empty string, so stamp_changed compares "" against "" and reports 'unchanged'. The hook then skips its work on every build — including the first one on a virgin worktree, where the cache announces a hit before it has ever been populated. Observed on Arch with the examples/paseo config: desvio_install printed 'dependencies current - skipping npm ci' into a build tree with no node_modules at all, and the build failed four steps later in packages/protocol with 'Cannot find module zod-aot'. Before, with no stamp file: digest '', stamp_changed -> unchanged After, with no stamp file: digest 3996615849, stamp_changed -> changed git hash-object --stdin rather than passing the path, so the bytes are hashed as-is and no clean filter can change the digest. Existing stamps are invalidated once by the algorithm change, costing one extra run of each guarded hook. tests/run.sh: 464 passed, 0 failed. Co-Authored-By: Claude Opus 5 --- lib/common.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/common.sh b/lib/common.sh index 8e45686..2f1ee37 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -291,17 +291,26 @@ default_base() { # A missing input is recorded as absent rather than being an error: for a # skip-the-work-if-nothing-changed hint, "the file is gone" means changed, and # turning a cache miss into a failed build would be the wrong trade. +# +# git hash-object rather than shasum, for the reason already given above +# decision_key: it is the one hashing tool guaranteed to be present, since +# desvio cannot run at all without git. shasum ships with macOS Perl but is +# absent on stock Arch and on minimal container images, and its absence is +# silent here — the command substitution yields an empty digest, a missing +# stamp file reads as the empty string too, and stamp_changed compares the +# two and reports 'unchanged'. The hook then skips its work on every build, +# starting with the very first one on a virgin worktree. stamp_digest() { local name="$1"; shift ( cd "$DESVIO_WORKTREE" || exit 1 local f for f in "$@"; do if [ -f "$f" ]; then - printf '%s\0%s\0' "$f" "$(shasum -a 256 < "$f" | cut -d' ' -f1)" + printf '%s\0%s\0' "$f" "$(git hash-object --stdin < "$f")" else printf '%s\0absent\0' "$f" fi - done | shasum -a 256 | cut -d' ' -f1 ) + done | git hash-object --stdin ) } stamp_changed() {