cookbook: add cookbook_apply_patches helper for Rule 2 external patches (v6.0 2026)

Per local/AGENTS.md Rule 2 (NO OVERLAY-STYLE PATCHES — AMENDED 2026),
big external projects (mesa, libdrm, wayland, qt, KF6, KWin, SDDM,
llvm, libepoxy, pipewire, wireplumber) apply their Red Bear edits as
external patches in local/patches/<component>/[0-9]*.patch on top of
the upstream checkout. Recipes for these projects previously inlined
the same 7-line bash loop (`cd $COOKBOOK_SOURCE; for p in
.../*.patch; do git apply ...; done; cd $COOKBOOK_BUILD`).

The cookbook_apply_patches helper centralizes this loop and adds
three quality improvements over the inline version:

  1. Idempotence: each patch is checked with `git apply --reverse
     --check` before applying. If the patch is already applied (e.g.
     a partial re-cook after a previous successful build), the helper
     skips it instead of failing with 'patch already applied'.
  2. Failure accounting: applied/skipped/failed counts are reported
     at the end of the run, so a single failed patch doesn't silently
     abort the entire build chain.
  3. Single source of truth: any future change to the patch application
     semantics (e.g. supporting 3-way merges, --3way, or a different
     check algorithm) happens in one place, not across 12+ recipes.

The helper is loaded into every recipe's build environment via the
existing cookbook shell-script injection in src/cook/script.rs and is
called as:

    cookbook_apply_patches "${REDBEAR_PATCHES_DIR}"

This commit is the cookbook-side change. The 4 existing Rule 2
migration recipes (mesa, libdrm, pipewire, wireplumber) are refactored
in the next commit to call this helper instead of inlining the loop.
This commit is contained in:
2026-06-10 01:06:27 +03:00
parent 5f5eec1c49
commit 1a291fbb95
+59
View File
@@ -199,6 +199,65 @@ function cookbook_cargo_packages {
done
}
# Apply Red Bear OS external patches (Rule 2 from local/AGENTS.md) on top
# of the upstream checkout. Recipes for big external projects (mesa,
# libdrm, wayland, qt, KF6, KWin, SDDM, llvm, libepoxy, pipewire,
# wireplumber, …) call this helper from their [build].script.
#
# Usage from a recipe's [build].script:
#
# cookbook_apply_patches "${COOKBOOK_RECIPE}/../../../local/patches/<component>"
#
# Or, when the patches live next to the recipe:
#
# cookbook_apply_patches "${COOKBOOK_RECIPE}/patches"
#
# The helper:
# 1. cd's into ${COOKBOOK_SOURCE} (the upstream checkout) so `git apply`
# works on real source files
# 2. For each [0-9]*.patch in the dir, checks if the patch is already
# applied (via `git apply --reverse --check`) and skips it if so.
# This makes the helper idempotent — a partial re-cook after a
# previous successful build doesn't fail with "patch already applied".
# 3. Applies the patch with `git apply`. Exits non-zero on failure so
# the cookbook surfaces the error to the user.
# 4. Returns the caller to ${COOKBOOK_BUILD} so subsequent build
# commands (meson/ninja/make) operate on the build dir as usual.
function cookbook_apply_patches {
local patches_dir="$1"
if [ -z "${patches_dir}" ] || [ ! -d "${patches_dir}" ]; then
echo "cookbook_apply_patches: no patches dir at '${patches_dir}'" >&2
return 1
fi
# The cookbook runs the build script with cwd = the build dir, but
# `git apply` needs to run inside the source tree (the upstream
# checkout), so cd there first.
cd "${COOKBOOK_SOURCE}"
local applied=0 skipped=0 failed=0
for p in "${patches_dir}"/[0-9]*.patch; do
[ -f "$p" ] || continue
# `git apply --reverse --check` succeeds when the patch is
# already applied. If it's NOT applied, --reverse --check fails
# with non-zero — exactly what we want to detect.
if git apply --reverse --check "$p" >/dev/null 2>&1; then
echo "cookbook_apply_patches: already applied, skipping: $(basename "$p")"
skipped=$((skipped + 1))
continue
fi
echo "cookbook_apply_patches: applying $(basename "$p")"
if ! git apply "$p"; then
echo "cookbook_apply_patches: FAILED to apply $(basename "$p")" >&2
failed=$((failed + 1))
else
applied=$((applied + 1))
fi
done
# Return to the build dir for the rest of the build
cd "${COOKBOOK_BUILD}"
echo "cookbook_apply_patches: applied=$applied skipped=$skipped failed=$failed"
[ "$failed" -eq 0 ]
}
# configure template
COOKBOOK_CONFIGURE="${COOKBOOK_SOURCE}/configure"
COOKBOOK_CONFIGURE_FLAGS=(