diff --git a/local/scripts/verify-tracked-sources.sh b/local/scripts/verify-tracked-sources.sh index afe78a9bf3..5655cc7af5 100755 --- a/local/scripts/verify-tracked-sources.sh +++ b/local/scripts/verify-tracked-sources.sh @@ -217,23 +217,36 @@ done # tree. They are therefore the LEAST protected and the MOST irreplaceable code # in the repository, so uncommitted drift in them stops the build outright # rather than printing a note that scrolls past. -# FIRST-PARTY recipes. Everything here is Red Bear's own code with no upstream -# anywhere. Add new internal programs to this list -- if it is ours and it is -# not a fork of something external, it belongs here. -# redbear-* the redbear-prefixed daemons, drivers and tools -# cub internal -# tlc internal -# Note the two shapes: `cub` is staged out of tree (no escaping path deps, so -# staging protects it), while `tlc` is exempt because its cargo manifest has a -# path dependency that escapes its source tree -- so for tlc this gate is the -# ONLY thing standing between a bad sed and unrecoverable loss. +# FIRST-PARTY detection, DERIVED -- deliberately not a hardcoded list. +# +# A name list was the first attempt (redbear-*, then cub, then tlc) and it was +# wrong in principle: protection that depends on someone remembering to edit +# this file is not protection. Every new internal program would start out +# unguarded, and the omission is invisible until the code is already lost. +# `tlc` proved the point -- it is first-party, it is exempt from out-of-tree +# staging, and nothing but this gate protects it, yet it matched no pattern. +# +# The real property is structural: OUR code has no upstream to restore from. +# So a recipe is first-party when its recipe.toml records no fetchable origin +# -- no `tar =`, no `git =`, and no upstream URL. That currently identifies ~96 +# recipes, against the 3 the list covered. +# +# The heuristic ERRS TOWARD first-party on purpose. A vendored recipe that +# records its origin only in prose gets classified as ours, which merely makes +# drift fatal instead of a warning -- conservative. The opposite mistake, a +# first-party recipe treated as vendored, is the one that loses irreplaceable +# work, so the default must fail in this direction. redbear_is_firstparty() { - case "$1" in - */redbear-*/source/*) return 0 ;; - */cub/source/*) return 0 ;; - */tlc/source/*) return 0 ;; - esac - return 1 + local path="$1" dir + dir="$(dirname "$path")" + # Walk up to the recipe root (the directory holding recipe.toml). + while [ "$dir" != "." ] && [ "$dir" != "/" ] && [ ! -f "$dir/recipe.toml" ]; do + dir="$(dirname "$dir")" + done + [ -f "$dir/recipe.toml" ] || return 1 + grep -qE '^[[:space:]]*(tar|git)[[:space:]]*=' "$dir/recipe.toml" && return 1 + grep -qE 'upstream:[[:space:]]*http|https?://[^[:space:]]+\.(tar|git)' "$dir/recipe.toml" && return 1 + return 0 } firstparty_dirty=0