feat(dirty-content-fingerprint): xce-build.sh computes dev-loop fingerprint
Adds an independent dirty_fingerprint computation to xce-build.sh: sha256 over git diff HEAD's output plus the sorted content of untracked, non-ignored files (git ls-files --others --exclude-standard), truncated to 8 hex chars. Resolves to empty on a clean tree or if the hash computation itself fails -- commit_id's own computation and -dirty suffix are left completely untouched. Zero working-tree/index mutation. Verified independently by review with real builds (HEAD pinned to control for concurrent background commits): distinguishes different uncommitted content, reproduces identical fingerprints for identical content, excludes .gitignore'd files, degrades gracefully under 3 independently-injected failure modes without aborting the build, applies to every profile, and leaves the original feature's regression script passing unmodified. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
13fc840f8c
commit
c9d40ba180
2 changed files with 53 additions and 6 deletions
|
|
@ -116,7 +116,56 @@ if [ -z "$build_time" ]; then
|
|||
echo "WARNING: xce-build.sh could not determine build_time (resolved empty) -- version info will be missing/incorrect in this build!" >&2
|
||||
fi
|
||||
|
||||
MESON_OPTS+=(-Dcommit_id="$commit_id" -Dbuild_time="$build_time")
|
||||
# dirty-content-fingerprint task 2.1: dirty_fingerprint, computed
|
||||
# INDEPENDENTLY of commit_id above -- commit_id's own computation
|
||||
# (including its -dirty suffix) is intentionally left untouched by this
|
||||
# block; this only adds a new, parallel value. Empty when the tree is
|
||||
# clean, or when the tree is dirty but the hash computation itself fails
|
||||
# (Requirement 5.1 -- never fabricate a value; commit_id's own untouched
|
||||
# -dirty suffix already signals "modified" in that fallback case, consumed
|
||||
# by a later task's --version composition, not here). When the tree is
|
||||
# dirty and the computation succeeds: a short sha256 prefix over `git diff
|
||||
# HEAD`'s output (tracked modifications, staged or unstaged) concatenated
|
||||
# with the raw content of every file `git ls-files --others
|
||||
# --exclude-standard` lists (untracked, non-ignored -- Requirement 1.4),
|
||||
# in a stable sorted order for determinism. Zero working-tree mutation --
|
||||
# reads only, no git add/stash/anything that touches the index or working
|
||||
# tree.
|
||||
dirty_fingerprint=""
|
||||
if [ -n "$(git status --porcelain 2>/dev/null)" ]; then
|
||||
fp_ok=1
|
||||
fp_tmp=""
|
||||
list_tmp=""
|
||||
if ! fp_tmp="$(mktemp 2>/dev/null)" || [ -z "$fp_tmp" ]; then
|
||||
fp_ok=0
|
||||
fi
|
||||
if [ "$fp_ok" = 1 ] && ! git diff HEAD >"$fp_tmp" 2>/dev/null; then
|
||||
fp_ok=0
|
||||
fi
|
||||
if [ "$fp_ok" = 1 ]; then
|
||||
if ! list_tmp="$(mktemp 2>/dev/null)" || [ -z "$list_tmp" ]; then
|
||||
fp_ok=0
|
||||
elif ! git ls-files -z --others --exclude-standard 2>/dev/null | LC_ALL=C sort -z >"$list_tmp"; then
|
||||
fp_ok=0
|
||||
else
|
||||
while IFS= read -r -d '' f; do
|
||||
if ! cat -- "$f" >>"$fp_tmp" 2>/dev/null; then
|
||||
fp_ok=0
|
||||
break
|
||||
fi
|
||||
done <"$list_tmp"
|
||||
fi
|
||||
fi
|
||||
if [ "$fp_ok" = 1 ]; then
|
||||
if fp="$(sha256sum <"$fp_tmp" 2>/dev/null | cut -c1-8)" && [ -n "$fp" ]; then
|
||||
dirty_fingerprint="$fp"
|
||||
fi
|
||||
fi
|
||||
[ -n "$fp_tmp" ] && rm -f "$fp_tmp"
|
||||
[ -n "$list_tmp" ] && rm -f "$list_tmp"
|
||||
fi
|
||||
|
||||
MESON_OPTS+=(-Dcommit_id="$commit_id" -Dbuild_time="$build_time" -Ddirty_fingerprint="$dirty_fingerprint")
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [component] [profile|build_dir] [build_dir] [--incremental]"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue