build system: engine preserves ALL RedBear-added files across a rebase
Data-loss bug: rsync --delete during a rebase dropped RedBear-added files that carry no __redox__ token (a Redox Wayland-crash wrapper .sh, a utmp compat header, a generated D-Bus interface) because the capture was grep-on-marker only. The engine now, for EVERY vendored rebase, fetches pristine(Vold) and carries forward every committed file absent from Vold (content-agnostic, matched by path) — so RedBear additions survive. If Vold cannot be fetched it rejects (manual) rather than produce a lossy tree. New tests E20 (non-marker added file preserved) + Vold fixtures for the rebase cases. 41 tests green.
This commit is contained in:
@@ -171,47 +171,57 @@ for dir in "${RECIPES[@]}"; do
|
||||
lv=$(apply_patch "$base/source" "$pf"); [ "$lv" = FAIL ] && preject=1
|
||||
done
|
||||
|
||||
# --- capture + reapply baked delta (changes beyond patches) ---
|
||||
# --- preserve RedBear additions + reapply baked Redox deltas ---
|
||||
# This runs for EVERY vendored rebase (not only marker-bearing ones): a
|
||||
# RedBear-added file (e.g. a Redox Wayland-crash wrapper .sh, a utmp compat
|
||||
# header) has no __redox__ token, so a grep-only capture misses it and
|
||||
# rsync --delete drops it. We compare against pristine(Vold) by PATH to keep
|
||||
# every RedBear addition, content-agnostic.
|
||||
breject=0
|
||||
if [ "$baked" -gt 0 ] && [ "$vold" != unknown ]; then
|
||||
# Derive the old-version URL: replace the full version, then the
|
||||
# major.minor directory component (KDE mirrors nest tarballs under a
|
||||
# major.minor dir, e.g. .../frameworks/6.28/foo-6.28.0.tar.xz -> 6.10/foo-6.10.0).
|
||||
if [ "$vold" != unknown ]; then
|
||||
# Old-version URL: replace the full version, then the major.minor dir
|
||||
# component (KDE mirrors nest under .../6.28/foo-6.28.0 -> 6.10/foo-6.10.0).
|
||||
oldurl="${url//$vnew/$vold}"
|
||||
vnm="${vnew%.*}"; vom="${vold%.*}"
|
||||
[ "$vnm" != "$vnew" ] && [ "$vnm" != "$vom" ] && oldurl="${oldurl//$vnm/$vom}"
|
||||
if download "$oldurl" "$WORK/$name-old.tar"; then
|
||||
op="$WORK/$name-old"; rm -rf "$op"; mkdir -p "$op"; tar xf "$WORK/$name-old.tar" -C "$op" 2>/dev/null
|
||||
otop="$(tar tf "$WORK/$name-old.tar" 2>/dev/null | head -1 | cut -d/ -f1)"; mv "$op/$otop" "$op/source" 2>/dev/null
|
||||
# For each Redox-marker file uncovered by patches, port its delta onto base.
|
||||
# A shim must NEVER be silently dropped: any failure -> breject (manual).
|
||||
relroot="${dir#$ROOT/}" # repo-relative recipe dir (git show needs this)
|
||||
while IFS= read -r line; do
|
||||
rel="${line#*/source/}"
|
||||
gitf="$WORK/gitf"
|
||||
if ! git -C "$ROOT" show "HEAD:$relroot/source/$rel" > "$gitf" 2>/dev/null || [ ! -s "$gitf" ]; then
|
||||
breject=1; continue # cannot read the Redox-modified file from HEAD
|
||||
fi
|
||||
relroot="${dir#$ROOT/}" # repo-relative recipe dir (git needs this)
|
||||
gitf="$WORK/gitf"
|
||||
|
||||
# (A) Carry forward every committed file absent from pristine(Vold): these
|
||||
# are RedBear additions upstream never had. Skip the stamp and files
|
||||
# the new pristine/patches already provide.
|
||||
while IFS= read -r rel; do
|
||||
[ "$rel" = ".redbear-src-version" ] && continue
|
||||
[ -e "$op/source/$rel" ] && continue # exists upstream -> not a RedBear addition
|
||||
[ -e "$base/source/$rel" ] && continue # already provided by pristine(Vnew) or a patch
|
||||
if ! git -C "$ROOT" show "HEAD:$relroot/source/$rel" > "$gitf" 2>/dev/null; then breject=1; continue; fi
|
||||
decorrupt "$gitf" > "$gitf.clean"
|
||||
if [ ! -f "$op/source/$rel" ]; then
|
||||
# Redox-ADDED file (absent from old upstream): carry it into the new tree verbatim.
|
||||
mkdir -p "$base/source/$(dirname "$rel")"; cp "$gitf.clean" "$base/source/$rel"; continue
|
||||
fi
|
||||
if [ ! -f "$base/source/$rel" ]; then
|
||||
breject=1; continue # file existed in old upstream+HEAD but gone in new -> manual
|
||||
fi
|
||||
if diff -q "$op/source/$rel" "$gitf.clean" >/dev/null 2>&1; then
|
||||
continue # marker is upstream's own (no Redox delta) -> nothing to port
|
||||
fi
|
||||
# Capture the delta to a file — do NOT pipe diff|patch. `diff` exits 1
|
||||
# whenever the files differ (always, here), and under `set -o pipefail`
|
||||
# that makes the pipeline look failed even when patch succeeded, which
|
||||
# would false-reject EVERY shim. Check patch's own exit status instead.
|
||||
diff -u "$op/source/$rel" "$gitf.clean" > "$WORK/delta.patch" 2>/dev/null
|
||||
if ! patch --fuzz=0 -s "$base/source/$rel" < "$WORK/delta.patch" >/dev/null 2>&1; then
|
||||
breject=1 # Redox delta will not apply cleanly at new upstream -> manual
|
||||
fi
|
||||
done < <(git -C "$ROOT" grep -lI "__redox__\|Q_OS_REDOX\|defined(__redox" HEAD -- "$dir/source" 2>/dev/null)
|
||||
mkdir -p "$base/source/$(dirname "$rel")"; cp "$gitf.clean" "$base/source/$rel"
|
||||
done < <(git -C "$ROOT" ls-tree -r --name-only HEAD -- "$relroot/source" | while IFS= read -r p; do printf '%s\n' "${p#"$relroot"/source/}"; done)
|
||||
|
||||
# (B) For marker-bearing files that ALSO exist in Vold (modified upstream
|
||||
# files), port the Redox delta. Added marker files were handled by (A).
|
||||
if [ "$baked" -gt 0 ]; then
|
||||
while IFS= read -r line; do
|
||||
rel="${line#*/source/}"
|
||||
[ -f "$op/source/$rel" ] || continue # added file -> already carried by (A)
|
||||
if ! git -C "$ROOT" show "HEAD:$relroot/source/$rel" > "$gitf" 2>/dev/null || [ ! -s "$gitf" ]; then
|
||||
breject=1; continue
|
||||
fi
|
||||
decorrupt "$gitf" > "$gitf.clean"
|
||||
if [ ! -f "$base/source/$rel" ]; then breject=1; continue; fi # gone in new upstream -> manual
|
||||
diff -q "$op/source/$rel" "$gitf.clean" >/dev/null 2>&1 && continue # marker is upstream's own
|
||||
# Capture delta to a file (never pipe diff|patch: diff exits 1 on any
|
||||
# difference and pipefail would false-reject every shim).
|
||||
diff -u "$op/source/$rel" "$gitf.clean" > "$WORK/delta.patch" 2>/dev/null
|
||||
if ! patch --fuzz=0 -s "$base/source/$rel" < "$WORK/delta.patch" >/dev/null 2>&1; then
|
||||
breject=1
|
||||
fi
|
||||
done < <(git -C "$ROOT" grep -lI "__redox__\|Q_OS_REDOX\|defined(__redox" HEAD -- "$dir/source" 2>/dev/null)
|
||||
fi
|
||||
else breject=1; fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ assert_eq "E2 source/ untouched" "$(cat "$d/source/f.c")" "code"; rm -rf "$d"
|
||||
|
||||
echo "=== engine: real rebase via file:// tarball ==="
|
||||
# E4 auto-ready divergent (0 patches, 0 baked): source/ 1.0.0 -> pristine 2.0.0
|
||||
mk_tar "$FIX/tarballs/e4-1.0.0.tar" "app-1.0.0" "main.c:v1\n" "old_only.c:gone\n"
|
||||
newtar="$FIX/tarballs/e4-2.0.0.tar"; mk_tar "$newtar" "app-2.0.0" ".redbear-src-version:2.0.0\n" "main.c:v2\n" "new_only.c:added\n"
|
||||
d="$(mk_recipe eng_ready "file://$newtar" "$(b3 "$newtar")")"
|
||||
mkdir -p "$d/source"; printf '1.0.0\n' >"$d/source/.redbear-src-version"; printf 'v1\n' >"$d/source/main.c"; printf 'gone\n' >"$d/source/old_only.c"
|
||||
@@ -122,7 +123,8 @@ assert_eq "E4 stamp updated to 2.0.0" "$(cat "$d/source/.redbear-src-version")"
|
||||
out="$($SYNC --check eng_ready 2>&1)"; assert_contains "E9 second run consistent" "$out" "consistent"; rm -rf "$d"
|
||||
|
||||
# E5/E6 patch apply vs reject
|
||||
newtar="$FIX/tarballs/e5-2.0.0.tar"; mk_tar "$newtar" "app-2.0.0" ".redbear-src-version:2.0.0\n" "f.c:line1\nline2\nline3\n"
|
||||
newtar="$FIX/tarballs/e5-2.0.0.tar"; mk_tar "$FIX/tarballs/e5-1.0.0.tar" "app-1.0.0" "f.c:line1\nline2\nline3\n"
|
||||
mk_tar "$newtar" "app-2.0.0" ".redbear-src-version:2.0.0\n" "f.c:line1\nline2\nline3\n"
|
||||
d="$(mk_recipe eng_patch "file://$newtar" "$(b3 "$newtar")"); "
|
||||
d="$FIX/local/recipes/eng_patch"
|
||||
printf 'tar = "file://%s"\nblake3 = "%s"\npatches = [ "add.patch" ]\n' "$newtar" "$(b3 "$newtar")" >>"$d/recipe.toml" 2>/dev/null
|
||||
@@ -159,6 +161,7 @@ assert_eq "E12 source/ untouched on DL-FAIL" "$(cat "$d/source/f.c")" "keep"; rm
|
||||
echo "=== blake3 reconcile ==="
|
||||
STALE=deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
|
||||
# E13 rebase reconciles recipe blake3 to the fetched source.tar
|
||||
mk_tar "$FIX/tarballs/e13-1.0.0.tar" "app-1.0.0" "m.c:v1\n"
|
||||
newtar="$FIX/tarballs/e13-2.0.0.tar"; mk_tar "$newtar" "app-2.0.0" ".redbear-src-version:2.0.0\n" "m.c:v2\n"
|
||||
d="$(mk_recipe eng_b3 "file://$newtar" "$STALE")"
|
||||
mkdir -p "$d/source"; printf '1.0.0\n' >"$d/source/.redbear-src-version"; printf 'v1\n' >"$d/source/m.c"
|
||||
@@ -223,6 +226,19 @@ $SYNC eng_shim3 >/dev/null 2>&1
|
||||
[ -f "$d/source/redoxonly.c" ] && grep -q "__redox__" "$d/source/redoxonly.c" && ok "E19 Redox-added file carried into new tree" || no "E19 added file carried" "redoxonly.c lost"
|
||||
rm -rf "$d"; gc rm
|
||||
|
||||
echo "=== E20 RedBear-ADDED file WITHOUT a __redox__ marker is preserved across rebase ==="
|
||||
mk_tar "$FIX/tarballs/w-1.0.0.tar" "app-1.0.0" "foo.c:x\n"
|
||||
mk_tar "$FIX/tarballs/w-2.0.0.tar" "app-2.0.0" "foo.c:x2\n" ".redbear-src-version:2.0.0\n"
|
||||
d="$(mk_recipe eng_add "file://$FIX/tarballs/w-2.0.0.tar" "$(b3 "$FIX/tarballs/w-2.0.0.tar")")"
|
||||
mkdir -p "$d/source"; printf '1.0.0\n' >"$d/source/.redbear-src-version"; printf 'x\n' >"$d/source/foo.c"
|
||||
# a RedBear launcher wrapper — NOT in upstream, and it contains NO __redox__ token
|
||||
printf '#!/bin/sh\n# RedBear launcher wrapper\nexec /usr/bin/app.real "$@"\n' >"$d/source/app-wrapper.sh"
|
||||
gc eng_add
|
||||
$SYNC eng_add >/dev/null 2>&1
|
||||
[ -f "$d/source/app-wrapper.sh" ] && grep -q "RedBear launcher" "$d/source/app-wrapper.sh" && ok "E20 non-marker RedBear-added file preserved" || no "E20 added file preserved" "app-wrapper.sh dropped by rebase"
|
||||
assert_eq "E20 upstream file updated to v2" "$(cat "$d/source/foo.c")" "x2"
|
||||
rm -rf "$d"; gc rm
|
||||
|
||||
echo ""
|
||||
echo "================ RESULT ================"
|
||||
echo " PASS: $PASS FAIL: $FAIL"
|
||||
|
||||
Reference in New Issue
Block a user