From 1a291fbb95490c45c5744f54fac01c2f9de9304f Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Wed, 10 Jun 2026 01:06:27 +0300 Subject: [PATCH] cookbook: add cookbook_apply_patches helper for Rule 2 external patches (v6.0 2026) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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//[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. --- src/cook/script.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/cook/script.rs b/src/cook/script.rs index cbfad10ff7..ab03041241 100644 --- a/src/cook/script.rs +++ b/src/cook/script.rs @@ -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/" +# +# 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=(