sirius-press/tools/refresh-patches.sh

108 lines
3.7 KiB
Bash
Raw Normal View History

build(sirius-press): build from the vendored subtree instead of a download The subtree is in place, so everything that used to fetch and patch core at build time now just copies it. tools/build.sh copies wordpress/ — no download, no checksum step, because there is nothing to fetch and nothing to trust that is not already in the repository docker/Dockerfile COPY wordpress/ instead of curl + sha256 + patch; the build args and the `patch` package are gone docker-compose.yml no WP_VERSION / WP_URL / WP_SHA256 to keep in step tools/update-wordpress.sh is rewritten around what the subtree makes possible. It imports the pristine release onto sirius-press/wordpress-upstream and then `git subtree merge`s that branch, which three-way merges upstream against the fork's own commit. A patch either applies with fuzz and hopes or fails and leaves you re-deriving the change by hand; a merge conflict is resolved once, in the file, and the next release merges against the resolution. patches/ survives as documentation rather than mechanism, and is now generated: tools/refresh-patches.sh diffs the subtree against the pristine import and rewrites the directory, with --check for CI. It answers the question anyone auditing a fork asks first — what exactly did you change inside WordPress? — in a minute, which `git log wordpress/` cannot, because that log is mostly upstream imports. Generated documentation stays true; a hand-maintained record of a core diff drifts, and a stale one is worse than none because people trust it. One test change worth noting: the syntax sweep no longer walks all of wordpress/. It lints the fork's own PHP plus every core file patches/ says the fork touches, which keeps the suite at seven seconds instead of a minute while still covering the only core file that can break.
2026-09-21 03:19:28 +02:00
#!/usr/bin/env bash
# refresh-patches.sh — regenerate patches/ from what the fork actually changed.
#
# Since core is vendored, `patches/` is no longer how the build works — it is
# documentation. It answers the question anyone auditing this fork asks first:
# *what exactly did you change inside WordPress?* A directory of readable
# diffs answers that in a minute; `git log wordpress/` does not, because it is
# mostly upstream imports.
#
# Documentation that is generated stays true. Documentation that is maintained
# by hand drifts, and a stale record of a fork's core diff is worse than none,
# because people trust it.
#
# tools/refresh-patches.sh # rewrite patches/ from the tree
# tools/refresh-patches.sh --check # fail if it would change anything (CI)
set -euo pipefail
here="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
repo="$(git -C "$here" rev-parse --show-toplevel)"
# Ask git where we are rather than subtracting paths: on Windows
# --show-toplevel answers "D:/..." while $PWD is "/d/...", and the
# subtraction silently leaves an absolute path behind.
prefix="$(cd "$here" && git rev-parse --show-prefix)wordpress"
UPSTREAM_BRANCH="sirius-press/wordpress-upstream"
CHECK=0
for arg in "$@"; do
case "$arg" in
--check) CHECK=1 ;;
*) echo "unknown option: $arg" >&2; exit 2 ;;
esac
done
say() { printf '\033[1m→\033[0m %s\n' "$*"; }
die() { printf '\033[31merror:\033[0m %s\n' "$*" >&2; exit 1; }
git -C "$repo" rev-parse --verify --quiet "$UPSTREAM_BRANCH" >/dev/null \
|| die "the branch $UPSTREAM_BRANCH is missing; there is nothing to diff against."
# shellcheck source=wordpress.lock
source "$here/tools/wordpress.lock"
staging="$here/dist/.patch-refresh"
rm -rf "$staging"
mkdir -p "$staging"
say "comparing ${prefix}/ against pristine WordPress ${WP_VERSION}"
# Every path that differs between the vendored tree and the pristine import.
#
# Compared tree to tree, not commit to commit: the upstream branch keeps
# WordPress at its root while the subtree keeps it under a prefix, so a
# plain `git diff BRANCH HEAD -- <prefix>` compares two different path
# spaces and reports the whole distribution as added.
UPSTREAM_TREE="${UPSTREAM_BRANCH}^{tree}"
VENDORED_TREE="HEAD:${prefix}"
mapfile -t changed < <(
git -C "$repo" diff --name-only "$UPSTREAM_TREE" "$VENDORED_TREE"
)
if [ ${#changed[@]} -eq 0 ]; then
say "the fork changes nothing in core — writing an empty series"
fi
index=0
for file in "${changed[@]}"; do
[ -n "$file" ] || continue
index=$((index + 1))
slug="$(echo "$file" | tr '/.' '--' | tr -cd 'A-Za-z0-9-')"
out="$staging/$(printf '%04d' "$index")-${slug}.patch"
{
echo "Subject: [PATCH] ${file}"
echo
echo "The fork's change to this file, regenerated by tools/refresh-patches.sh."
echo "It is a record, not the mechanism: core is vendored under wordpress/ and"
echo "this diff is what distinguishes it from pristine upstream."
echo
echo "Applies to: WordPress ${WP_VERSION}"
git -C "$repo" diff "$UPSTREAM_TREE" "$VENDORED_TREE" -- "$file" | tail -n +3
} > "$out"
done
if [ "$CHECK" -eq 1 ]; then
if diff -rq "$here/patches" "$staging" >/dev/null 2>&1; then
say "patches/ matches the tree"
rm -rf "$staging"
exit 0
fi
diff -ru "$here/patches" "$staging" || true
rm -rf "$staging"
die "patches/ is out of date. Run tools/refresh-patches.sh and commit the result."
fi
rm -f "$here/patches"/*.patch
if [ "$index" -gt 0 ]; then
cp "$staging"/*.patch "$here/patches/"
fi
rm -rf "$staging"
say "wrote ${index} patch file(s) describing the fork's core diff"
for f in "$here/patches"/*.patch; do
[ -e "$f" ] || continue
printf ' %s (%s lines)\n' "$(basename "$f")" "$(grep -c '' "$f")"
done