6c25f4dd06
9th silent-failure bug: the version stamp was checked BEFORE the real code marker (Qt .cmake.conf / KDE KF_VERSION). A code-only revert leaves the stamp stale, and the stale stamp then reported the module 'consistent' -> the engine skipped a needed rebase and the validator false-passed a divergent tree. Both now check the authoritative code marker first and use the stamp only as a fallback for marker-less trees. The validator also learned KDE's KF_VERSION marker. Test E21.
105 lines
5.0 KiB
Bash
Executable File
105 lines
5.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# verify-external-source-versions.sh — detect recipe-vs-source VERSION divergence
|
|
# for tar-based (external upstream) recipes.
|
|
#
|
|
# Why this exists
|
|
# ---------------
|
|
# Several recipes under local/recipes/ vendor their upstream `source/` tree in
|
|
# git (the fork model) while ALSO declaring a `[source] tar = <url>` + `blake3`.
|
|
# A version bump that only rewrites `tar=`/`blake3=` (e.g. via
|
|
# bump-graphics-recipes.sh, or a manual edit) does NOT propagate into the
|
|
# committed source/ tree, nor does cookbook re-extract an existing source/ or
|
|
# re-verify an existing source.tar. The build then silently compiles the STALE
|
|
# version — exactly the Qt 6.11.0-vs-6.11.1 divergence that broke the desktop
|
|
# build (qtshadertools required 6.11.1 but qtbase was cooked from a 6.11.0 tree).
|
|
#
|
|
# This is the tar-recipe analogue of verify-fork-functions.sh (which guards the
|
|
# local/sources/ forks). It FAILS LOUDLY rather than letting a stale tree build.
|
|
#
|
|
# Checks per tar recipe (only when the relevant artifact is present):
|
|
# 1. source.tar blake3 == recipe blake3 (stale downloaded tarball)
|
|
# 2. source.tar top-dir version == recipe URL version (URL bumped, tar not)
|
|
# 3. vendored source/ version marker == recipe URL version
|
|
# (recipe bumped, committed tree not — the Qt class). Marker files:
|
|
# - .cmake.conf : QT_REPO_MODULE_VERSION "X.Y.Z" (Qt modules)
|
|
# - .redbear-src-version : plain "X.Y.Z" (generic stamp)
|
|
#
|
|
# Exit 0 = all consistent (or nothing to check). Exit 1 = divergence found.
|
|
# Gate: REDBEAR_SKIP_EXTERNAL_SOURCE_CHECK=1 bypasses (handled by caller).
|
|
|
|
set -u
|
|
|
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
QUIET=0
|
|
for a in "$@"; do case "$a" in --quiet) QUIET=1 ;; esac; done
|
|
|
|
have_b3() { command -v b3sum >/dev/null 2>&1; }
|
|
|
|
# Extract a dotted version (X.Y or X.Y.Z...) from a string; prints the LAST one,
|
|
# which for "qtbase-everywhere-src-6.11.1.tar.xz" is the upstream version.
|
|
ver_of() { grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)*' <<<"$1" | tail -1; }
|
|
|
|
FAIL=0
|
|
CHECKED=0
|
|
declare -a PROBLEMS=()
|
|
|
|
while IFS= read -r recipe; do
|
|
dir="$(dirname "$recipe")"
|
|
# recipe-declared tar URL + blake3 (first [source] tar= wins)
|
|
url="$(grep -m1 -E '^[[:space:]]*tar[[:space:]]*=' "$recipe" 2>/dev/null | sed -E 's/^[^"]*"([^"]+)".*/\1/')"
|
|
[ -n "$url" ] || continue
|
|
rblake="$(grep -m1 -E '^[[:space:]]*blake3[[:space:]]*=' "$recipe" 2>/dev/null | grep -oE '[0-9a-f]{64}')"
|
|
rver="$(ver_of "$(basename "$url")")"
|
|
[ -n "$rver" ] || continue
|
|
name="$(basename "$dir")"
|
|
CHECKED=$((CHECKED + 1))
|
|
|
|
# 1) cached source.tar blake3 must match recipe blake3
|
|
if [ -f "$dir/source.tar" ] && [ -n "$rblake" ] && have_b3; then
|
|
dblake="$(b3sum "$dir/source.tar" 2>/dev/null | awk '{print $1}')"
|
|
if [ -n "$dblake" ] && [ "$dblake" != "$rblake" ]; then
|
|
PROBLEMS+=("$name: cached source.tar blake3 ($dblake) != recipe blake3 ($rblake) — stale downloaded tarball; rm '$dir/source.tar' to re-fetch")
|
|
FAIL=1
|
|
fi
|
|
fi
|
|
|
|
# 2) source.tar top-dir version must match recipe URL version
|
|
if [ -f "$dir/source.tar" ]; then
|
|
tver="$(ver_of "$(tar tf "$dir/source.tar" 2>/dev/null | head -1)")"
|
|
if [ -n "$tver" ] && [ "$tver" != "$rver" ]; then
|
|
PROBLEMS+=("$name: source.tar is v$tver but recipe tar= is v$rver — URL bumped, tarball not; rm '$dir/source.tar' to re-fetch")
|
|
FAIL=1
|
|
fi
|
|
fi
|
|
|
|
# 3) vendored source/ version marker must match recipe URL version.
|
|
# ACTUAL code markers (.cmake.conf, KDE KF_VERSION) win over the generic
|
|
# .redbear-src-version stamp — a stale stamp must never mask the real code
|
|
# version and let a divergent tree pass.
|
|
if [ -d "$dir/source" ]; then
|
|
sver=""
|
|
if [ -f "$dir/source/.cmake.conf" ]; then
|
|
sver="$(ver_of "$(grep -m1 QT_REPO_MODULE_VERSION "$dir/source/.cmake.conf" 2>/dev/null)")"
|
|
fi
|
|
if [ -z "$sver" ] && [ -f "$dir/source/CMakeLists.txt" ]; then
|
|
sver="$(grep -m1 -E 'set\(KF_VERSION|project\([A-Za-z0-9_]+ VERSION [0-9]' "$dir/source/CMakeLists.txt" 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)"
|
|
fi
|
|
if [ -z "$sver" ] && [ -f "$dir/source/.redbear-src-version" ]; then
|
|
sver="$(ver_of "$(cat "$dir/source/.redbear-src-version" 2>/dev/null)")"
|
|
fi
|
|
if [ -n "$sver" ] && [ "$sver" != "$rver" ]; then
|
|
PROBLEMS+=("$name: vendored source/ is v$sver but recipe declares v$rver — the committed tree was never bumped; rebase source/ onto v$rver (see qt bump commits for the pattern)")
|
|
FAIL=1
|
|
fi
|
|
fi
|
|
done < <(find "$ROOT/local/recipes" -name recipe.toml -not -path '*/wip/*' 2>/dev/null)
|
|
|
|
if [ "$FAIL" != "0" ]; then
|
|
echo "FAIL: external source version divergence ($CHECKED tar recipes checked):" >&2
|
|
for p in "${PROBLEMS[@]}"; do echo " - $p" >&2; done
|
|
exit 1
|
|
fi
|
|
|
|
[ "$QUIET" = "1" ] || echo ">>> Preflight: external tar-recipe source versions consistent ($CHECKED checked)."
|
|
exit 0
|