Files
RedBear-OS/local/scripts/apply-patches.sh
T
vasilito 7c7399e0a6 feat: recipe durability guard — prevents build system from deleting local recipes
Add guard-recipes.sh with four modes:
- --verify: check all local/recipes have correct symlinks into recipes/
- --fix: repair broken symlinks (run before builds)
- --save-all: snapshot all recipe.toml into local/recipes/
- --restore: recreate all symlinks from local/recipes/ (run after sync-upstream)

Wired into apply-patches.sh (post-patch) and sync-upstream.sh (post-sync).
This prevents the build system from deleting recipe files during
cargo cook, make distclean, or upstream source refresh.
2026-04-30 18:47:03 +01:00

360 lines
16 KiB
Bash
Executable File

#!/usr/bin/env bash
# apply-patches.sh — Apply all Red Bear OS overlays on top of upstream Redox build system.
#
# Usage: ./local/scripts/apply-patches.sh [--force] [--dry-run]
#
# This script:
# 1. Applies build-system patches (rebranding, cookbook fixes, config, docs)
# 2. Ensures recipe patches are symlinked from local/patches/
# 3. Ensures custom recipe symlinks exist in recipes/
#
# WIP policy note:
# If upstream work is still under recipes/wip/, Red Bear may still ship from local/recipes/
# instead. This script therefore treats the local overlay as the durable source of truth.
#
# With --force: reapplies even if patches appear already applied.
# With --dry-run: shows what would change without making changes.
#
# SAFE: does not touch local/ directory. Only modifies upstream files.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
PATCHES_DIR="$REPO_ROOT/local/patches"
FORCE=""
DRY_RUN=0
cd "$REPO_ROOT"
# ── Helper ──────────────────────────────────────────────────────────
usage() {
cat <<'EOF'
Usage: ./local/scripts/apply-patches.sh [--force] [--dry-run]
Options:
--force attempt re-application even when checks fail
--dry-run show what would change without modifying files
EOF
}
for arg in "$@"; do
case "$arg" in
--force) FORCE="--force" ;;
--dry-run) DRY_RUN=1 ;;
-h|--help)
usage
exit 0
;;
*)
usage
exit 1
;;
esac
done
symlink() {
local target="$1" link="$2"
if [ -L "$link" ]; then
current="$(readlink "$link")"
if [ "$current" = "$target" ]; then
return 0 # already correct
fi
fi
if [ "$DRY_RUN" = "1" ]; then
dry_run_msg "would remove and relink $link -> $target"
return 0
fi
rm -f "$link"
ln -s "$target" "$link"
echo " linked $link -> $target"
}
dry_run_msg() {
if [ "$DRY_RUN" = "1" ]; then
echo " [dry-run] $*"
fi
}
# ── 1. Build-system patches ─────────────────────────────────────────
echo "==> Applying build-system patches..."
for patch_file in "$PATCHES_DIR"/build-system/[0-9]*.patch; do
[ -f "$patch_file" ] || continue
patch_name="$(basename "$patch_file")"
# Check if patch applies cleanly
if ! git apply --check "$patch_file" 2>/dev/null; then
# Patch does NOT apply cleanly — check if it's already applied
if git apply --reverse --check "$patch_file" 2>/dev/null; then
echo " SKIP $patch_name (already applied)"
continue
fi
# Reverse-check failed — maybe working tree diverged but patch is
# effectively applied. Use signature markers for robustness.
already_applied=0
case "$patch_name" in
001-rebrand-and-build.patch)
grep -q 'Red Bear OS' Makefile 2>/dev/null && already_applied=1
;;
002-cookbook-fixes.patch)
grep -q 'redbear_cookbook' Cargo.toml 2>/dev/null \
&& grep -q 'redbear_protected_recipe' src/cook/fetch.rs 2>/dev/null \
&& already_applied=1
;;
003-config.patch)
grep -q 'redbear-full' config/redbear-full.toml 2>/dev/null && already_applied=1
;;
004-docs-and-cleanup.patch)
grep -q 'Red Bear OS' README.md 2>/dev/null && already_applied=1
;;
005-qtbase-toolchain-elf-header.patch)
# This patch touches recipes/libs/qtbase; check for our marker
grep -q 'REDBEAR' recipes/libs/qtbase/recipe.toml 2>/dev/null && already_applied=1
;;
esac
if [ "$already_applied" -eq 1 ]; then
echo " SKIP $patch_name (already applied via signature marker)"
continue
fi
# Patch conflicts and is NOT already applied — this is a real problem
echo " FAIL $patch_name — conflicts with current tree"
echo " This likely means upstream has changed the target files."
echo " Patch file: $patch_file"
echo " Options:"
echo " 1. Resolve conflicts: edit the patch file to match new upstream"
echo " 2. Use --force to attempt re-application (may fail)"
if [ "$FORCE" != "--force" ]; then
echo " ABORT: unresolved patch conflict (use --force to override)"
exit 1
fi
fi
if [ "$DRY_RUN" = "1" ]; then
dry_run_msg "would apply $patch_name"
continue
fi
if git apply --whitespace=nowarn "$patch_file"; then
echo " OK $patch_name"
else
echo " FAIL $patch_name — apply failed (check conflicts above)"
echo " Patch file: $patch_file"
exit 1
fi
done
# ── 2. Recipe patches (kernel, base) ───────────────────────────────
echo "==> Linking recipe patches from local/patches/..."
symlink "../../../local/patches/kernel/redox.patch" "recipes/core/kernel/redox.patch"
symlink "../../../local/patches/base/redox.patch" "recipes/core/base/redox.patch"
symlink "../../../local/patches/base/P2-boot-runtime-fixes.patch" "recipes/core/base/P2-boot-runtime-fixes.patch"
# ── 3. Custom recipe symlinks ──────────────────────────────────────
echo "==> Linking custom recipes from local/recipes/..."
# Branding
mkdir -p recipes/branding
symlink "../../local/recipes/branding/redbear-release" "recipes/branding/redbear-release"
# Drivers
mkdir -p recipes/drivers
symlink "../../local/recipes/drivers/linux-kpi" "recipes/drivers/linux-kpi"
symlink "../../local/recipes/drivers/redbear-btusb" "recipes/drivers/redbear-btusb"
symlink "../../local/recipes/drivers/redbear-iwlwifi" "recipes/drivers/redbear-iwlwifi"
symlink "../../local/recipes/drivers/redox-driver-sys" "recipes/drivers/redox-driver-sys"
# GPU
mkdir -p recipes/gpu
symlink "../../local/recipes/gpu/amdgpu" "recipes/gpu/amdgpu"
symlink "../../local/recipes/gpu/redox-drm" "recipes/gpu/redox-drm"
# Library stubs / custom libs
mkdir -p recipes/libs
symlink "../../local/recipes/libs/libqrencode" "recipes/libs/libqrencode"
symlink "../../local/recipes/libs/libepoxy-stub" "recipes/libs/libepoxy-stub"
symlink "../../local/recipes/libs/libudev-stub" "recipes/libs/libudev-stub"
symlink "../../local/recipes/libs/lcms2-stub" "recipes/libs/lcms2-stub"
symlink "../../local/recipes/libs/libdisplay-info-stub" "recipes/libs/libdisplay-info-stub"
symlink "../../local/recipes/libs/libxcvt-stub" "recipes/libs/libxcvt-stub"
symlink "../../local/recipes/libs/zbus" "recipes/libs/zbus"
# System
mkdir -p recipes/system
symlink "../../local/recipes/system/cub" "recipes/system/cub"
symlink "../../local/recipes/system/evdevd" "recipes/system/evdevd"
symlink "../../local/recipes/system/redbear-firmware" "recipes/system/redbear-firmware"
symlink "../../local/recipes/system/firmware-loader" "recipes/system/firmware-loader"
symlink "../../local/recipes/system/iommu" "recipes/system/iommu"
symlink "../../local/recipes/system/redbear-hwutils" "recipes/system/redbear-hwutils"
symlink "../../local/recipes/system/redbear-info" "recipes/system/redbear-info"
symlink "../../local/recipes/system/redbear-btctl" "recipes/system/redbear-btctl"
symlink "../../local/recipes/system/redbear-netstat" "recipes/system/redbear-netstat"
symlink "../../local/recipes/system/redbear-netctl" "recipes/system/redbear-netctl"
symlink "../../local/recipes/system/redbear-netctl-console" "recipes/system/redbear-netctl-console"
symlink "../../local/recipes/system/redbear-wifictl" "recipes/system/redbear-wifictl"
symlink "../../local/recipes/system/redbear-traceroute" "recipes/system/redbear-traceroute"
symlink "../../local/recipes/system/redbear-mtr" "recipes/system/redbear-mtr"
symlink "../../local/recipes/system/redbear-nmap" "recipes/system/redbear-nmap"
symlink "../../local/recipes/system/redbear-meta" "recipes/system/redbear-meta"
symlink "../../local/recipes/system/udev-shim" "recipes/system/udev-shim"
symlink "../../local/recipes/system/redbear-sessiond" "recipes/system/redbear-sessiond"
symlink "../../local/recipes/system/redbear-authd" "recipes/system/redbear-authd"
symlink "../../local/recipes/system/redbear-session-launch" "recipes/system/redbear-session-launch"
symlink "../../local/recipes/system/redbear-greeter" "recipes/system/redbear-greeter"
symlink "../../local/recipes/system/redbear-dbus-services" "recipes/system/redbear-dbus-services"
symlink "../../local/recipes/system/redbear-notifications" "recipes/system/redbear-notifications"
symlink "../../local/recipes/system/redbear-upower" "recipes/system/redbear-upower"
symlink "../../local/recipes/system/redbear-udisks" "recipes/system/redbear-udisks"
symlink "../../local/recipes/system/redbear-polkit" "recipes/system/redbear-polkit"
# Core additions
mkdir -p recipes/core
symlink "../../local/recipes/core/ext4d" "recipes/core/ext4d"
symlink "../../local/recipes/core/grub" "recipes/core/grub"
# Resolve WIP conflict: recipes/wip/services/grub also exists,
# so redirect the entire directory to our local overlay to ensure
# COOKBOOK_RECIPE resolves to a directory that contains grub.cfg
if [ -d "recipes/wip/services/grub" ] && [ ! -L "recipes/wip/services/grub" ]; then
backup_name="recipes/wip/services/grub.upstream-backup-$(date +%Y%m%d-%H%M%S)"
if [ "$DRY_RUN" = "1" ]; then
dry_run_msg "would backup recipes/wip/services/grub to $backup_name and replace with symlink"
else
echo " backing up upstream recipes/wip/services/grub -> $backup_name"
mv "recipes/wip/services/grub" "$backup_name"
fi
fi
if [ ! -e "recipes/wip/services/grub" ]; then
symlink "../../../local/recipes/core/grub" "recipes/wip/services/grub"
fi
# Wayland additions
mkdir -p recipes/wip/wayland
symlink "../../../local/recipes/wayland/qt6-wayland-smoke" "recipes/wip/wayland/qt6-wayland-smoke"
# KDE / Phase 6 recipes
mkdir -p recipes/kde
symlink "../../local/recipes/kde/plasma-desktop" "recipes/kde/plasma-desktop"
symlink "../../local/recipes/kde/plasma-workspace" "recipes/kde/plasma-workspace"
symlink "../../local/recipes/kde/plasma-framework" "recipes/kde/plasma-framework"
symlink "../../local/recipes/kde/plasma-wayland-protocols" "recipes/kde/plasma-wayland-protocols"
symlink "../../local/recipes/kde/kwin" "recipes/kde/kwin"
symlink "../../local/recipes/kde/kirigami" "recipes/kde/kirigami"
symlink "../../local/recipes/kde/kirigami" "recipes/kde/kf6-kirigami"
symlink "../../local/recipes/kde/kdecoration" "recipes/kde/kdecoration"
symlink "../../local/recipes/kde/kf6-extra-cmake-modules" "recipes/kde/kf6-extra-cmake-modules"
symlink "../../local/recipes/kde/kf6-kcoreaddons" "recipes/kde/kf6-kcoreaddons"
symlink "../../local/recipes/kde/kf6-kwidgetsaddons" "recipes/kde/kf6-kwidgetsaddons"
symlink "../../local/recipes/kde/kf6-kconfig" "recipes/kde/kf6-kconfig"
symlink "../../local/recipes/kde/kf6-ki18n" "recipes/kde/kf6-ki18n"
symlink "../../local/recipes/kde/kf6-kcodecs" "recipes/kde/kf6-kcodecs"
symlink "../../local/recipes/kde/kf6-kguiaddons" "recipes/kde/kf6-kguiaddons"
symlink "../../local/recipes/kde/kf6-kcolorscheme" "recipes/kde/kf6-kcolorscheme"
symlink "../../local/recipes/kde/kf6-kauth" "recipes/kde/kf6-kauth"
symlink "../../local/recipes/kde/kf6-kitemmodels" "recipes/kde/kf6-kitemmodels"
symlink "../../local/recipes/kde/kf6-kitemviews" "recipes/kde/kf6-kitemviews"
symlink "../../local/recipes/kde/kf6-karchive" "recipes/kde/kf6-karchive"
symlink "../../local/recipes/kde/kf6-kwindowsystem" "recipes/kde/kf6-kwindowsystem"
symlink "../../local/recipes/kde/kf6-knotifications" "recipes/kde/kf6-knotifications"
symlink "../../local/recipes/kde/kf6-kjobwidgets" "recipes/kde/kf6-kjobwidgets"
symlink "../../local/recipes/kde/kf6-kconfigwidgets" "recipes/kde/kf6-kconfigwidgets"
symlink "../../local/recipes/kde/kf6-kcrash" "recipes/kde/kf6-kcrash"
symlink "../../local/recipes/kde/kf6-kdbusaddons" "recipes/kde/kf6-kdbusaddons"
symlink "../../local/recipes/kde/kf6-kglobalaccel" "recipes/kde/kf6-kglobalaccel"
symlink "../../local/recipes/kde/kf6-kservice" "recipes/kde/kf6-kservice"
symlink "../../local/recipes/kde/kf6-kpackage" "recipes/kde/kf6-kpackage"
symlink "../../local/recipes/kde/kf6-kiconthemes" "recipes/kde/kf6-kiconthemes"
symlink "../../local/recipes/kde/kf6-kxmlgui" "recipes/kde/kf6-kxmlgui"
symlink "../../local/recipes/kde/kf6-ktextwidgets" "recipes/kde/kf6-ktextwidgets"
symlink "../../local/recipes/kde/kf6-solid" "recipes/kde/kf6-solid"
symlink "../../local/recipes/kde/kf6-sonnet" "recipes/kde/kf6-sonnet"
symlink "../../local/recipes/kde/kf6-kio" "recipes/kde/kf6-kio"
symlink "../../local/recipes/kde/kf6-kbookmarks" "recipes/kde/kf6-kbookmarks"
symlink "../../local/recipes/kde/kf6-kcompletion" "recipes/kde/kf6-kcompletion"
symlink "../../local/recipes/kde/kf6-kdeclarative" "recipes/kde/kf6-kdeclarative"
symlink "../../local/recipes/kde/kf6-kcmutils" "recipes/kde/kf6-kcmutils"
symlink "../../local/recipes/kde/kf6-kidletime" "recipes/kde/kf6-kidletime"
symlink "../../local/recipes/kde/kf6-kwayland" "recipes/kde/kf6-kwayland"
symlink "../../local/recipes/kde/kf6-knewstuff" "recipes/kde/kf6-knewstuff"
symlink "../../local/recipes/kde/kf6-kwallet" "recipes/kde/kf6-kwallet"
symlink "../../local/recipes/kde/kf6-prison" "recipes/kde/kf6-prison"
# ── 4. New files not in upstream ────────────────────────────────────
echo "==> Ensuring Red Bear OS-specific files exist..."
# redbear.ipxe (network boot)
if [ ! -f redbear.ipxe ] && [ ! -L redbear.ipxe ]; then
if [ "$DRY_RUN" = "1" ]; then
dry_run_msg "would create redbear.ipxe"
else
cat > redbear.ipxe <<'IPXE'
#!ipxe
kernel bootloader-live.efi
initrd http://${next-server}:8080/redbear-live.iso
boot
IPXE
echo " created redbear.ipxe"
fi
fi
# redbear-full config (not in upstream)
if [ ! -f config/redbear-full.toml ] && [ ! -L config/redbear-full.toml ]; then
if [ "$DRY_RUN" = "1" ]; then
dry_run_msg "would create config/redbear-full.toml"
else
cat > config/redbear-full.toml <<'TOML'
# Red Bear OS Full Configuration
# Complete desktop + all Red Bear OS custom drivers and tools
#
# Build: make all CONFIG_NAME=redbear-full
# Live: make live CONFIG_NAME=redbear-live-full
include = ["desktop.toml"]
[general]
# 2GB filesystem — plenty for full desktop + drivers
# (desktop.toml sets 650MB, but we want headroom for our custom packages)
filesystem_size = 2048
[packages]
# Red Bear OS branding (os-release, hostname, motd)
redbear-release = {}
# ext4 filesystem support (our custom port)
ext4d = {}
# Red Bear OS driver infrastructure
redox-driver-sys = {}
linux-kpi = {}
firmware-loader = {}
# Input layer
evdevd = {}
udev-shim = {}
# GPU driver (AMD — modesetting display core)
redox-drm = {}
amdgpu = {}
# Red Bear OS meta-package (dependencies, default config)
redbear-meta = {}
TOML
echo " created config/redbear-full.toml"
fi
else
echo " config/redbear-full.toml already exists — not overwriting"
fi
echo ""
echo "==> All Red Bear OS patches applied. Ready to build."
if [ "$DRY_RUN" = "1" ]; then
echo " [dry-run mode — no changes were made]"
fi
echo ""
echo "==> Guarding recipe durability..."
./local/scripts/guard-recipes.sh --fix 2>/dev/null || echo " (guard-recipes.sh not found — run manually)"
echo " make all CONFIG_NAME=redbear-full"