#!/usr/bin/env bash # test-vendored-source-staleness.sh — regression test for build-redbear.sh's # vendored-recipe source-staleness invalidation (the loop that rm's a recipe's # target/ when its git-committed source/ tree changes). # # Why: cookbook keys its build cache on source.tar's hash, but the actual build # input for a vendored recipe is source/. A version bump that changes source/ # without changing source.tar (the Qt 6.11.0->6.11.1 case) otherwise reuses a # stale stage and ships the wrong version. This test proves the loop SEEDs on # first sight (no spurious rebuild), stays quiet when unchanged, and invalidates # on both committed and uncommitted source/ changes. # # The loop body below MUST stay in sync with build-redbear.sh. Zero network. set -u PASS=0; FAIL=0 ok(){ PASS=$((PASS+1)); printf ' ok %s\n' "$1"; } no(){ FAIL=$((FAIL+1)); printf ' FAIL %s\n %s\n' "$1" "${2:-}"; } T="$(mktemp -d)"; trap 'rm -rf "$T"' EXIT PROJECT_ROOT="$T"; C_INFO=">>>"; C_RESET="" git -C "$T" init -q; git -C "$T" config user.email t@t; git -C "$T" config user.name t # --- loop body copied verbatim from build-redbear.sh (keep in sync) --- run_loop(){ while IFS= read -r _rt; do _rdir="$(dirname "$_rt")"; _sdir="$_rdir/source" [ -d "$_sdir" ] || continue _tgt="$_rdir/target/x86_64-unknown-redox" [ -f "$_tgt/stage.pkgar" ] || continue _relsrc="${_sdir#"$PROJECT_ROOT"/}" _tree="$(git -C "$PROJECT_ROOT" rev-parse "HEAD:$_relsrc" 2>/dev/null || echo "")" [ -n "$_tree" ] || continue _dirty="" git -C "$PROJECT_ROOT" diff --quiet HEAD -- "$_relsrc" 2>/dev/null || _dirty="-dirty" [ -n "$(git -C "$PROJECT_ROOT" ls-files --others --exclude-standard -- "$_relsrc" 2>/dev/null)" ] && _dirty="-dirty" _cur="${_tree}${_dirty}"; _fp="$_tgt/.redbear-source-tree" _last="$(cat "$_fp" 2>/dev/null || echo "")" if [ -z "$_last" ]; then printf '%s\n' "$_cur" > "$_fp"; echo "SEED" elif [ "$_cur" != "$_last" ]; then echo "INVALIDATE"; rm -rf "$_rdir/target" else echo "UNCHANGED"; fi done < <(find "$PROJECT_ROOT/local/recipes" -name recipe.toml -not -path '*/wip/*' 2>/dev/null) } R="$T/local/recipes/foo" mkdir -p "$R/source" "$R/target/x86_64-unknown-redox" echo v1 > "$R/source/f.c"; printf '[package]\nname="foo"\n' > "$R/recipe.toml" echo pkgar > "$R/target/x86_64-unknown-redox/stage.pkgar" git -C "$T" add -A; git -C "$T" commit -qm init [ "$(run_loop)" = SEED ] && [ -d "$R/target" ] && ok "first observation seeds + keeps target" || no "seed" [ "$(run_loop)" = UNCHANGED ] && [ -d "$R/target" ] && ok "unchanged keeps target" || no "unchanged" echo v2 > "$R/source/f.c"; git -C "$T" add -A; git -C "$T" commit -qm change [ "$(run_loop)" = INVALIDATE ] && [ ! -d "$R/target" ] && ok "committed source change invalidates target" || no "committed-change" # rebuild target + reseed, then dirty (uncommitted) change mkdir -p "$R/target/x86_64-unknown-redox"; echo pkgar > "$R/target/x86_64-unknown-redox/stage.pkgar" run_loop >/dev/null echo v3-dirty > "$R/source/f.c" # uncommitted [ "$(run_loop)" = INVALIDATE ] && [ ! -d "$R/target" ] && ok "uncommitted (dirty) source change invalidates" || no "dirty-change" # untracked new file in source/ also counts as dirty mkdir -p "$R/target/x86_64-unknown-redox"; echo pkgar > "$R/target/x86_64-unknown-redox/stage.pkgar" git -C "$T" add -A; git -C "$T" commit -qm v3; run_loop >/dev/null echo new > "$R/source/added.c" # untracked [ "$(run_loop)" = INVALIDATE ] && ok "untracked new file in source/ invalidates" || no "untracked-file" echo " PASS: $PASS FAIL: $FAIL" [ "$FAIL" -eq 0 ] && { echo " ALL GREEN"; exit 0; } || exit 1