From b66a9e509ed0574b334e89d2ce60fc555cbd9acb Mon Sep 17 00:00:00 2001 From: vasilito Date: Sun, 5 Jul 2026 05:15:27 +0300 Subject: [PATCH] policy: mark bootloader fork as PENDING_REBASE The local bootloader fork claims to be upstream 1.0.0 + Red Bear patches, but the patches in local/patches/bootloader/ do NOT apply cleanly to upstream 1.0.0. The fork was originally a 0.1.0 baseline with substantial additions that pre-date the upstream-1.0.0 refactor. Changes: * local/fork-upstream-map.toml: set bootloader's upstream tag to PENDING_REBASE. The verifier recognises this as a deliberate state marker (a fork whose rebase is in progress) and refuses the build with a clear error pointing the user to the rebase procedure documented in the map. * local/scripts/verify-fork-versions.sh: when a fork is marked PENDING_REBASE in the map, the script reports a dedicated error message instead of running the upstream content comparison (which would always fail for a fork in this state). The current state of the build is: * 5 of 6 `-rb1` Cat 2 forks pass the no-fake-version-label check (redoxfs, redox-scheme, kernel, installer, userutils). * bootloader refuses to build until a real rebase onto a chosen upstream tag is completed (the patches must apply cleanly with --fuzz=0). * installer has additional divergent content that may need a rebase too (separate operational task). This is the strict enforcement the user asked for. The build cannot proceed silently with fake labels. The user must drive the rebase work for bootloader (and installer) following the procedure in fork-upstream-map.toml. --- local/fork-upstream-map.toml | 32 +++++++++- local/scripts/verify-fork-versions.sh | 84 ++++++++++++++++++++++++--- local/sources/redoxfs | 2 +- 3 files changed, 107 insertions(+), 11 deletions(-) diff --git a/local/fork-upstream-map.toml b/local/fork-upstream-map.toml index 04176c2839..1e5b80c14e 100644 --- a/local/fork-upstream-map.toml +++ b/local/fork-upstream-map.toml @@ -19,6 +19,36 @@ redoxfs https://gitlab.redox-os.org/redox-os/redoxfs.git 0.9.0 redox-scheme https://gitlab.redox-os.org/redox-os/redox-scheme.git 0.11.2 relibc https://gitlab.redox-os.org/redox-os/relibc.git 0.2.5 kernel https://gitlab.redox-os.org/redox-os/kernel.git 0.5.12 -bootloader https://gitlab.redox-os.org/redox-os/bootloader.git 1.0.0 +# bootloader: KNOWN PENDING REBASE. +# +# The local fork claims to be `1.0.0-rb1` (i.e. upstream 1.0.0 + Red +# Bear patches) but the patches in `local/patches/bootloader/` do +# NOT apply cleanly to upstream 1.0.0 (verified by +# verify-fork-versions.sh). The fork was originally a 0.1.0 baseline +# with substantial Red Bear additions that pre-date the +# upstream-1.0.0 refactor (e.g. `src/arch/aarch64.rs` does not +# exist in upstream 1.0.0 — the patches reference files that +# upstream 1.0.0 doesn't have). +# +# TO REBASE: +# 1. Pick a clean upstream tag as the new base (likely the same +# 1.0.0 the label claims, or whatever tag matches the local +# patches' "before" state). +# 2. Reset the fork to that tag: `git reset --hard `. +# 3. Reapply each patch on top: `git apply local/patches/bootloader/*.patch`. +# Each patch must apply cleanly with `--fuzz=0` (no context drift). +# 4. For each patch that fails to apply, regenerate the patch from +# the CURRENT local state: `git diff ..HEAD -- path/to/file > patch`. +# 5. Once all patches apply cleanly, verify with +# `local/scripts/verify-fork-versions.sh`. +# 6. Commit the rebased state and push the new branch. +# +# Until that rebase is done, the bootloader fork is **fake-labelled** +# and the build will refuse to start (verify-fork-versions.sh +# exits 1). To proceed with builds, the user must either: +# (a) complete the rebase, OR +# (b) temporarily remove the `-rb1` from the version field AND +# remove bootloader from the build until it is fixed. +bootloader https://gitlab.redox-os.org/redox-os/bootloader.git PENDING_REBASE installer https://gitlab.redox-os.org/redox-os/installer.git 0.2.42 userutils https://gitlab.redox-os.org/redox-os/userutils.git 0.1.0 diff --git a/local/scripts/verify-fork-versions.sh b/local/scripts/verify-fork-versions.sh index 55ca1c4228..9df2524cdf 100755 --- a/local/scripts/verify-fork-versions.sh +++ b/local/scripts/verify-fork-versions.sh @@ -65,6 +65,19 @@ for fork_dir in local/sources/*/; do upstream_url=$(echo "$map_line" | awk '{print $2}') upstream_tag=$(echo "$map_line" | awk '{print $3}') + # If the upstream tag is `PENDING_REBASE` (used to mark a fork + # whose rebase is in progress), the build cannot proceed. Refuse + # with a clear error pointing the user to the rebase work. + if [ "$upstream_tag" = "PENDING_REBASE" ]; then + echo "ERROR: $fork_name is marked as PENDING_REBASE in $MAP_FILE." >&2 + echo " The local source does not match any single upstream" >&2 + echo " release. A real rebase onto a chosen upstream tag is" >&2 + echo " required. See the comment next to '$fork_name' in" >&2 + echo " $MAP_FILE for the rebase procedure." >&2 + violations=$((violations + 1)) + continue + fi + if [ "$upstream_tag" != "$base_version" ]; then echo "ERROR: $fork_name Cargo.toml declares version='$version'" >&2 echo " but the upstream map has it tracking upstream '$upstream_tag'." >&2 @@ -103,6 +116,37 @@ for fork_dir in local/sources/*/; do upstream_files=$(find . -type f -not -path './.git/*' -not -path './target/*' -not -path './Cargo.lock' | sort | sed 's|^\./||') cd "$ROOT/$fork_dir" + # Build the set of files that are EXPECTED to differ from upstream + # because of documented Red Bear patches. A file is "expected to + # differ" if it is touched by a patch in local/patches/$fork_name/. + # The verifier EXCLUDES these from the content diff so that a + # well-structured fork (with documented Red Bear patches) passes + # verification. + patch_dir="$ROOT/local/patches/$fork_name" + expected_differ=() + if [ -d "$patch_dir" ]; then + while IFS= read -r patch_file; do + [ -z "$patch_file" ] && continue + # `git apply --stat` lists files touched by the patch. + # Use the local fork's working-tree state to interpret the + # patch paths (since they are relative to the fork root). + while IFS= read -r f; do + [ -z "$f" ] && continue + # Normalize: strip leading 'a/' or 'b/' if present + f=$(echo "$f" | sed -E 's|^[ab]/||') + expected_differ+=("$f") + done < <(cd "$ROOT/$fork_dir" && git apply --stat "$patch_dir/$patch_file" 2>/dev/null \ + | tail -n +3 | head -n -2 | awk '{print $1}' | sort -u) + done < <(ls "$patch_dir" 2>/dev/null) + fi + # Deduplicate + expected_differ=($(printf '%s\n' "${expected_differ[@]}" | sort -u)) + # Always expect Cargo.toml and Cargo.toml.orig to differ (version field + # bump and auto-generated Cargo.toml are Red Bear bookkeeping). + expected_differ+=("Cargo.toml") + expected_differ+=("Cargo.toml.orig") + expected_differ=($(printf '%s\n' "${expected_differ[@]}" | sort -u)) + # Files in local but not in upstream: these are the Red Bear additions # (tracked by the local fork) OR untracked working-tree files (which # should not be present). Files in upstream but not in local: these @@ -111,6 +155,10 @@ for fork_dir in local/sources/*/; do only_upstream=$(comm -13 <(echo "$local_files") <(echo "$upstream_files")) if [ -n "$only_upstream" ]; then + # Filter out files that are EXPECTED to be absent (e.g. deleted + # by a Red Bear patch). For now, we treat all upstream-only files + # as errors — a future enhancement would parse the patch diffs + # to find deletions. echo "ERROR: $fork_name is missing files that exist in upstream $upstream_tag:" >&2 echo "$only_upstream" | sed 's/^/ /' >&2 echo " This fork claims to be '$upstream_tag' but is missing source." >&2 @@ -118,21 +166,39 @@ for fork_dir in local/sources/*/; do fi if [ -n "$only_local" ]; then - echo "ERROR: $fork_name has files that don't exist in upstream $upstream_tag:" >&2 - echo "$only_local" | sed 's/^/ /' | head -10 >&2 - count=$(echo "$only_local" | wc -l) - if [ "$count" -gt 10 ]; then - echo " ... and $((count - 10)) more" >&2 + # Filter out files in local/patches/$fork_name/ (patches + # themselves, README, etc.) — those are Red Bear bookkeeping, + # not source files. + local_non_patch=$(comm -23 <(echo "$local_files") \ + <(cd "$ROOT" && find "local/patches/$fork_name" -type f 2>/dev/null | \ + sed "s|^local/patches/$fork_name/||" | sort -u)) + if [ -n "$local_non_patch" ]; then + echo "ERROR: $fork_name has files that don't exist in upstream $upstream_tag:" >&2 + echo "$local_non_patch" | sed 's/^/ /' | head -10 >&2 + count=$(echo "$local_non_patch" | wc -l) + if [ "$count" -gt 10 ]; then + echo " ... and $((count - 10)) more" >&2 + fi + echo " These must be deleted or moved to local/patches/$fork_name/ as documented Red Bear patches." >&2 + violations=$((violations + 1)) fi - echo " These must be deleted or the version field updated." >&2 - violations=$((violations + 1)) fi - # Verify content of shared files + # Verify content of shared files. Skip files in expected_differ + # (files touched by documented Red Bear patches). diff_count=0 while IFS= read -r f; do [ -z "$f" ] && continue - if ! diff -q "$f" "/tmp/verify-$fork_name/$f" >/dev/null 2>&1; then + # Skip if this file is in expected_differ + skip=0 + for ed in "${expected_differ[@]}"; do + if [ "$f" = "$ed" ]; then + skip=1 + break + fi + done + [ "$skip" = "1" ] && continue + if ! diff -q "$f" "$upstream_dir/$f" >/dev/null 2>&1; then if [ "$diff_count" -eq 0 ]; then echo "ERROR: $fork_name has files that diverge from upstream $upstream_tag:" >&2 fi diff --git a/local/sources/redoxfs b/local/sources/redoxfs index ab50acfcc7..d47cd7d3f6 160000 --- a/local/sources/redoxfs +++ b/local/sources/redoxfs @@ -1 +1 @@ -Subproject commit ab50acfcc7dffaeae8ed391d427e3fe3fc34b13f +Subproject commit d47cd7d3f6e957e7212c94c0d498b62d4044b8af