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:
@@ -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=(
|
||||
|
||||
Reference in New Issue
Block a user