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=(