212 lines
6.9 KiB
Bash
212 lines
6.9 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# update-wordpress.sh — move the fork onto a new WordPress release.
|
||
|
|
#
|
||
|
|
# tools/update-wordpress.sh 7.1.2
|
||
|
|
# tools/update-wordpress.sh 7.1.2 --refresh # also rewrite the patch series
|
||
|
|
# tools/update-wordpress.sh 7.1.2 --diff wp-admin/install.php
|
||
|
|
#
|
||
|
|
# Fetches the release, verifies it against the SHA-1 wordpress.org publishes,
|
||
|
|
# applies the patch series, and reports whether the fork still fits.
|
||
|
|
#
|
||
|
|
# Nothing is committed and tools/wordpress.lock is only rewritten once the
|
||
|
|
# series has actually applied — so a failed run leaves the fork building the
|
||
|
|
# last known-good version rather than a broken one.
|
||
|
|
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
here="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
|
|
cd "$here"
|
||
|
|
|
||
|
|
VERSION="${1:-}"
|
||
|
|
REFRESH=0
|
||
|
|
DIFF_FILE=""
|
||
|
|
|
||
|
|
shift || true
|
||
|
|
while [ $# -gt 0 ]; do
|
||
|
|
case "$1" in
|
||
|
|
--refresh) REFRESH=1 ;;
|
||
|
|
--diff) shift; DIFF_FILE="${1:-}" ;;
|
||
|
|
*) echo "unknown option: $1" >&2; exit 2 ;;
|
||
|
|
esac
|
||
|
|
shift
|
||
|
|
done
|
||
|
|
|
||
|
|
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> [--refresh] [--diff <file>]"
|
||
|
|
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]] || die "'$VERSION' does not look like a WordPress version"
|
||
|
|
|
||
|
|
# shellcheck source=wordpress.lock
|
||
|
|
source tools/wordpress.lock
|
||
|
|
CURRENT="$WP_VERSION"
|
||
|
|
|
||
|
|
WORK="$here/dist/.upstream"
|
||
|
|
CACHE="$here/dist/.cache"
|
||
|
|
mkdir -p "$WORK" "$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 "verifying against wordpress.org's published SHA-1"
|
||
|
|
published="$(curl -fsSL "${URL}.sha1" 2>/dev/null || true)"
|
||
|
|
actual_sha1="$(sha1sum "$TARBALL" | cut -d' ' -f1)"
|
||
|
|
if [ -z "$published" ]; then
|
||
|
|
warn "wordpress.org did not serve a .sha1 for this release; continuing on the SHA-256 recorded below"
|
||
|
|
elif [ "$published" != "$actual_sha1" ]; then
|
||
|
|
rm -f "$TARBALL"
|
||
|
|
die "SHA-1 mismatch — the download does not match what wordpress.org publishes.
|
||
|
|
published $published
|
||
|
|
got $actual_sha1"
|
||
|
|
fi
|
||
|
|
NEW_SHA256="$(sha256sum "$TARBALL" | cut -d' ' -f1)"
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------ unpack
|
||
|
|
|
||
|
|
say "unpacking"
|
||
|
|
rm -rf "${WORK:?}/new" "${WORK:?}/pristine" "${WORK:?}/wordpress"
|
||
|
|
tar -xzf "$TARBALL" -C "$WORK"
|
||
|
|
[ -d "$WORK/wordpress" ] || die "the tarball did not contain a wordpress/ directory"
|
||
|
|
mv "$WORK/wordpress" "$WORK/new"
|
||
|
|
cp -R "$WORK/new" "$WORK/pristine"
|
||
|
|
|
||
|
|
# --------------------------------------------------------- what changed?
|
||
|
|
|
||
|
|
if [ -n "$DIFF_FILE" ]; then
|
||
|
|
old_tarball="$CACHE/wordpress-${CURRENT}.tar.gz"
|
||
|
|
if [ ! -f "$old_tarball" ]; then
|
||
|
|
say "fetching $CURRENT for comparison"
|
||
|
|
curl -fsSL -o "$old_tarball" "$WP_URL"
|
||
|
|
fi
|
||
|
|
rm -rf "$WORK/old"
|
||
|
|
mkdir -p "$WORK/old"
|
||
|
|
tar -xzf "$old_tarball" -C "$WORK/old"
|
||
|
|
say "upstream's own changes to $DIFF_FILE between $CURRENT and $VERSION:"
|
||
|
|
diff -u "$WORK/old/wordpress/$DIFF_FILE" "$WORK/new/$DIFF_FILE" || true
|
||
|
|
echo
|
||
|
|
fi
|
||
|
|
|
||
|
|
# ------------------------------------------------------------ the series
|
||
|
|
|
||
|
|
shopt -s nullglob
|
||
|
|
patches=(patches/*.patch)
|
||
|
|
shopt -u nullglob
|
||
|
|
|
||
|
|
failed=0
|
||
|
|
fuzzed=0
|
||
|
|
|
||
|
|
if [ ${#patches[@]} -eq 0 ]; then
|
||
|
|
say "no patches to apply"
|
||
|
|
else
|
||
|
|
say "applying ${#patches[@]} patch(es) to WordPress $VERSION"
|
||
|
|
for patch in "${patches[@]}"; do
|
||
|
|
name="$(basename "$patch")"
|
||
|
|
output="$(cd "$WORK/new" && patch -p1 -F3 --forward < "$here/$patch" 2>&1)" && rc=0 || rc=$?
|
||
|
|
if [ "$rc" -ne 0 ]; then
|
||
|
|
echo " FAILED $name"
|
||
|
|
echo "$output" | sed 's/^/ /'
|
||
|
|
failed=1
|
||
|
|
elif echo "$output" | grep -q 'with fuzz'; then
|
||
|
|
echo " fuzz $name"
|
||
|
|
echo "$output" | grep 'with fuzz' | sed 's/^/ /'
|
||
|
|
fuzzed=1
|
||
|
|
else
|
||
|
|
echo " ok $name"
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo
|
||
|
|
|
||
|
|
if [ "$failed" -eq 1 ]; then
|
||
|
|
cat >&2 <<EOF
|
||
|
|
$(printf '\033[31mThe patch series no longer fits WordPress %s.\033[0m' "$VERSION")
|
||
|
|
|
||
|
|
Upstream has rewritten code the fork patches. Nothing has changed here — the
|
||
|
|
lock file still points at $CURRENT and builds still produce a working fork.
|
||
|
|
|
||
|
|
To fix it:
|
||
|
|
1. The unpacked tree is at dist/.upstream/new — edit it by hand.
|
||
|
|
2. Diff it against the pristine copy:
|
||
|
|
diff -u dist/.upstream/pristine/<file> dist/.upstream/new/<file>
|
||
|
|
3. Replace the hunks in the failing patch with the result, keeping its
|
||
|
|
Subject: header and explanation.
|
||
|
|
4. Run this script again.
|
||
|
|
EOF
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# ------------------------------------------------------------ refresh
|
||
|
|
|
||
|
|
if [ "$REFRESH" -eq 1 ]; then
|
||
|
|
say "regenerating the patch series against $VERSION"
|
||
|
|
for patch in "${patches[@]}"; do
|
||
|
|
file="$(grep -m1 '^--- a/' "$patch" | sed 's|^--- a/||')"
|
||
|
|
[ -n "$file" ] || { warn "$(basename "$patch") has no file header; left alone"; continue; }
|
||
|
|
header="$(sed -n '1,/^--- a\//p' "$patch" | sed '$d')"
|
||
|
|
{
|
||
|
|
echo "$header" | sed "s/^Applies to: WordPress .*/Applies to: WordPress $VERSION/"
|
||
|
|
diff -u "$WORK/pristine/$file" "$WORK/new/$file" \
|
||
|
|
| sed -e "1s|.*|--- a/$file|" -e "2s|.*|+++ b/$file|"
|
||
|
|
} > "$patch.new"
|
||
|
|
mv "$patch.new" "$patch"
|
||
|
|
echo " refreshed $(basename "$patch")"
|
||
|
|
done
|
||
|
|
elif [ "$fuzzed" -eq 1 ]; then
|
||
|
|
warn "the series applied with fuzz. Run again with --refresh so the next release starts clean."
|
||
|
|
fi
|
||
|
|
|
||
|
|
# --------------------------------------------------------------- the lock
|
||
|
|
|
||
|
|
say "updating tools/wordpress.lock"
|
||
|
|
python3 - "$VERSION" "$URL" "$NEW_SHA256" "$actual_sha1" <<'PY'
|
||
|
|
import io, sys
|
||
|
|
version, url, sha256, sha1 = sys.argv[1:5]
|
||
|
|
path = 'tools/wordpress.lock'
|
||
|
|
out = []
|
||
|
|
for line in io.open(path, encoding='utf-8'):
|
||
|
|
if line.startswith('WP_VERSION='):
|
||
|
|
out.append(f'WP_VERSION={version}\n')
|
||
|
|
elif line.startswith('WP_URL='):
|
||
|
|
out.append(f'WP_URL={url}\n')
|
||
|
|
elif line.startswith('WP_SHA256='):
|
||
|
|
out.append(f'WP_SHA256={sha256}\n')
|
||
|
|
elif line.startswith('WP_SHA1='):
|
||
|
|
out.append(f'WP_SHA1={sha1}\n')
|
||
|
|
else:
|
||
|
|
out.append(line)
|
||
|
|
io.open(path, 'w', encoding='utf-8', newline='').write(''.join(out))
|
||
|
|
PY
|
||
|
|
|
||
|
|
# The compose defaults mirror the lock so a plain `docker compose build`
|
||
|
|
# cannot drift onto a different core.
|
||
|
|
sed -i \
|
||
|
|
-e "s|WP_VERSION: \${WP_VERSION:-.*}|WP_VERSION: \${WP_VERSION:-$VERSION}|" \
|
||
|
|
-e "s|WP_URL: \${WP_URL:-.*}|WP_URL: \${WP_URL:-$URL}|" \
|
||
|
|
-e "s|WP_SHA256: \${WP_SHA256:-.*}|WP_SHA256: \${WP_SHA256:-$NEW_SHA256}|" \
|
||
|
|
docker/docker-compose.yml
|
||
|
|
|
||
|
|
cat <<EOF
|
||
|
|
|
||
|
|
$(printf '\033[32mSirius Press now builds on WordPress %s.\033[0m' "$VERSION")
|
||
|
|
|
||
|
|
tools/wordpress.lock $CURRENT -> $VERSION
|
||
|
|
docker/docker-compose.yml build args updated
|
||
|
|
|
||
|
|
Next:
|
||
|
|
tests/run.sh
|
||
|
|
tools/build.sh
|
||
|
|
then walk through wp-admin/install.php once — the setup wizard is the only
|
||
|
|
patched file, so it is the only thing this can have broken.
|
||
|
|
|
||
|
|
EOF
|