Files
RedBear-OS/local/scripts/validate-patches.sh
T
vasilito b9874d0941 feat: USB storage read/write proof + full Red Bear OS tree sync
Add redbear-usb-storage-check in-guest binary that validates USB mass
storage read and write I/O: discovers /scheme/disk/ devices, writes a
test pattern to sector 2048, reads it back, verifies match, restores
original content. Updates test-usb-storage-qemu.sh with write-proof
verification step.

Includes all accumulated Red Bear OS work: kernel patches, relibc
patches, driver infrastructure, DRM/GPU, KDE recipes, firmware,
validation tooling, build system hardening, and documentation.
2026-05-03 23:03:24 +01:00

124 lines
3.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# validate-patches.sh — Check that all recipe patches apply cleanly.
#
# Usage: ./local/scripts/validate-patches.sh [--rebase] [recipe...]
#
# Without arguments, validates all recipes with patches.
# With --rebase, runs patch --dry-run -R to check if the patch can
# be reverse-applied (meaning it IS currently applied).
# With recipe names/paths, validates only those recipes.
#
# Exit code: number of failed patches (0 = all clean).
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
cd "$ROOT"
MODE="apply" # apply | rebase
FAILED=0
CHECKED=0
TOTAL_PATCHES=0
red() { printf "\033[1;31m%s\033[0m\n" "$*"; }
green(){ printf "\033[1;32m%s\033[0m\n" "$*"; }
cyan() { printf "\033[1;36m%s\033[0m\n" "$*"; }
while [[ $# -gt 0 ]]; do
case "$1" in
--rebase) MODE="rebase"; shift ;;
*) break ;;
esac
done
RECIPE_DIRS=("$@")
if [ ${#RECIPE_DIRS[@]} -eq 0 ]; then
mapfile -t RECIPE_DIRS < <(find recipes -name "recipe.toml" -exec dirname {} \; | sort)
fi
validate_patch() {
local recipe_dir="$1"
local patch_name="$2"
local patch_file="$3"
local source_dir="$4"
local flags="--strip=1 --batch --fuzz=0"
if [ "$MODE" = "rebase" ]; then
# Check if patch can be reverse-applied (it IS currently applied)
if patch --dry-run --directory "$source_dir" $flags -R < "$patch_file" >/dev/null 2>&1; then
return 0 # already applied → OK
else
echo " $(red NEEDS REBASE) $patch_name"
FAILED=$((FAILED + 1))
return 1
fi
fi
# Forward-apply check
if patch --dry-run --directory "$source_dir" $flags < "$patch_file" >/dev/null 2>&1; then
return 0
fi
# Show the actual error for diagnosis
echo " $(red FAILED) $patch_name"
patch --dry-run --directory "$source_dir" $flags < "$patch_file" 2>&1 | head -5 | sed 's/^/ /'
FAILED=$((FAILED + 1))
return 1
}
for recipe_dir in "${RECIPE_DIRS[@]}"; do
recipe_toml="$recipe_dir/recipe.toml"
[ -f "$recipe_toml" ] || continue
# Extract patch list from recipe.toml
patches=$(grep -o '"[^"]*\.patch"' "$recipe_toml" 2>/dev/null | tr -d '"')
[ -n "$patches" ] || continue
source_dir="$recipe_dir/source"
if [ ! -d "$source_dir" ]; then
echo "$(cyan SKIP) $recipe_dir — no source directory"
continue
fi
recipe_failed=0
recipe_checked=0
for patch_name in $patches; do
# Resolve patch file path (handle relative paths like ../../../local/patches/...)
patch_file="$recipe_dir/$patch_name"
if [ ! -f "$patch_file" ]; then
echo " $(red MISSING) $patch_name ($patch_file)"
FAILED=$((FAILED + 1))
continue
fi
recipe_checked=$((recipe_checked + 1))
TOTAL_PATCHES=$((TOTAL_PATCHES + 1))
validate_patch "$recipe_dir" "$patch_name" "$patch_file" "$source_dir" || true
done
if [ "$recipe_checked" -gt 0 ]; then
CHECKED=$((CHECKED + 1))
if [ "$recipe_failed" -eq 0 ]; then
echo "$(green OK) $recipe_dir$recipe_checked patch(es) clean"
fi
fi
done
echo ""
echo "──────────────────────────────────────────"
echo " Recipes checked: $CHECKED"
echo " Total patches: $TOTAL_PATCHES"
echo " Failed: $FAILED"
echo "──────────────────────────────────────────"
if [ "$FAILED" -eq 0 ]; then
echo "$(green All patches apply cleanly)"
else
red "$FAILED patch(es) need rebasing or fixing"
fi
exit $FAILED