#!/usr/bin/env bash # update-wordpress.sh — bring a new WordPress release into the fork. # # tools/update-wordpress.sh 7.1.2 # # Two steps, and the second is the one that matters: # # 1. Import the pristine release onto the `sirius-press/wordpress-upstream` # branch — one commit per version, nothing but upstream, never edited. # 2. `git subtree merge` that branch into wordpress/, which three-way merges # it against the fork's own commits on top of the last import. # # That second step is why core is vendored rather than patched at build time. # A three-way merge understands that upstream changed lines A and B while the # fork changed line C, and only stops when they overlap. It also leaves a # conflict you resolve once, in the file, instead of a patch you re-derive # every release. # # Nothing is pushed. Run it, look at the merge, run the tests, then commit. set -euo pipefail here="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" repo="$(git -C "$here" rev-parse --show-toplevel)" prefix="${here#"$repo"/}/wordpress" VERSION="${1:-}" say() { printf '\033[1m→\033[0m %s\n' "$*"; } warn() { printf '\033[33mwarning:\033[0m %s\n' "$*" >&2; } die() { printf '\033[31merror:\033[0m %s\n' "$*" >&2; exit 1; } [ -n "$VERSION" ] || die "usage: tools/update-wordpress.sh " [[ "$VERSION" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]] || die "'$VERSION' does not look like a WordPress version" # shellcheck source=wordpress.lock source "$here/tools/wordpress.lock" CURRENT="$WP_VERSION" [ "$VERSION" != "$CURRENT" ] || die "the fork is already on WordPress $VERSION" UPSTREAM_BRANCH="sirius-press/wordpress-upstream" git -C "$repo" rev-parse --verify --quiet "$UPSTREAM_BRANCH" >/dev/null \ || die "the branch $UPSTREAM_BRANCH is missing. It holds the pristine upstream imports that the subtree merges against; without it this fork cannot take an upstream release. See docs/upstream-merges.md." # A subtree merge writes to the working tree, so it has to be clean — at least # for the paths involved. Refuse early rather than half way through. if ! git -C "$repo" diff --quiet -- "$prefix" 2>/dev/null; then die "wordpress/ has uncommitted changes. Commit or stash them first." fi CACHE="$here/dist/.cache" mkdir -p "$CACHE" URL="https://wordpress.org/wordpress-${VERSION}.tar.gz" TARBALL="$CACHE/wordpress-${VERSION}.tar.gz" # ------------------------------------------------------------------- fetch if [ ! -f "$TARBALL" ]; then say "downloading WordPress $VERSION" curl -fsSL -o "$TARBALL.part" "$URL" || die "could not download $URL — does that version exist?" mv "$TARBALL.part" "$TARBALL" fi say "checking it against the SHA-1 wordpress.org publishes" published="$(curl -fsSL "${URL}.sha1" 2>/dev/null || true)" actual_sha1="$(sha1sum "$TARBALL" | cut -d' ' -f1)" if [ -z "$published" ]; then warn "wordpress.org served no .sha1 for this release; recording the sha256 below unverified" elif [ "$published" != "$actual_sha1" ]; then rm -f "$TARBALL" die "SHA-1 mismatch — the download is not what wordpress.org publishes. published $published got $actual_sha1" fi NEW_SHA256="$(sha256sum "$TARBALL" | cut -d' ' -f1)" # ------------------------------------------- import onto the upstream branch WORKTREE="$here/dist/.vendor-import" say "importing the pristine tree onto $UPSTREAM_BRANCH" rm -rf "$WORKTREE" git -C "$repo" worktree add --quiet "$WORKTREE" "$UPSTREAM_BRANCH" cleanup() { git -C "$repo" worktree remove --force "$WORKTREE" >/dev/null 2>&1 || true } trap cleanup EXIT # Replace the tree wholesale: files upstream deleted have to disappear, or the # subtree merge would keep resurrecting them. find "$WORKTREE" -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} + tar -xzf "$TARBALL" -C "$WORKTREE" --strip-components=1 git -C "$WORKTREE" add -A if git -C "$WORKTREE" diff --cached --quiet; then die "WordPress $VERSION is byte-identical to what is already imported." fi git -C "$WORKTREE" \ -c user.name="Silent Mode" -c user.email="hephaestus@silentmode.st" \ commit -q -m "WordPress ${VERSION} Pristine upstream, unpacked from the official wordpress.org tarball. ${URL} sha1 ${actual_sha1} (published by wordpress.org) sha256 ${NEW_SHA256} This branch carries nothing but upstream releases, one commit each, and is never edited." say "imported as $(git -C "$WORKTREE" rev-parse --short HEAD)" cleanup trap - EXIT # ------------------------------------------------------------ subtree merge say "merging into ${prefix}/" if git -C "$repo" \ -c user.name="Silent Mode" -c user.email="hephaestus@silentmode.st" \ subtree merge --prefix="$prefix" "$UPSTREAM_BRANCH" \ -m "merge: WordPress ${VERSION} into the vendored subtree" then merged=1 else merged=0 fi if [ "$merged" -eq 0 ]; then cat >&2 < ${VERSION} The merge and the lock update are staged as commits already; patches/ may have changed too. Before pushing: tests/run.sh tools/build.sh then walk through wp-admin/install.php once — the setup wizard is the only file this fork patches, so it is the only thing this can have broken. EOF