#!/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 -- ` 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