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.
This commit is contained in:
parent
34fd3f062c
commit
961cb108ca
12 changed files with 396 additions and 376 deletions
28
README.md
28
README.md
|
|
@ -121,7 +121,8 @@ plugins/
|
|||
sirius-press-sia-export/ the static export queue and uploader
|
||||
sirius-press-compat/ shims for plugins that insist on an admin email
|
||||
mu-plugins/ the bits that must load before plugins do
|
||||
patches/ the core diff — currently one file
|
||||
wordpress/ WordPress itself, vendored as a subtree, patched
|
||||
patches/ a generated record of the core diff — one file
|
||||
docker/ compose stack: MariaDB, PHP-FPM, nginx
|
||||
tools/ build, upstream update, release
|
||||
tests/ 138 unit checks plus a live end-to-end suite
|
||||
|
|
@ -130,19 +131,20 @@ docs/
|
|||
|
||||
### Where WordPress itself is
|
||||
|
||||
Not in this repository. `tools/wordpress.lock` pins an exact upstream version
|
||||
and its SHA-256; `tools/build.sh` and the Docker image each download it, verify
|
||||
the hash, and apply `patches/`.
|
||||
In `wordpress/`, as a git subtree, already patched. That is what gets built
|
||||
and what gets shipped — there is no download step and no checksum to trust at
|
||||
build time.
|
||||
|
||||
This deviates from the original plan of vendoring core as a git subtree, and
|
||||
the reason is arithmetic: WordPress 7.1.1 is 149 MB and 5,008 files, and the
|
||||
fork's entire core diff is 75 lines in one file. Carrying the former to express
|
||||
the latter would make every clone, every `git status` and every subtree split
|
||||
in the parent monorepo pay for a patch you can read in a minute. Upstream
|
||||
security releases still merge cleanly — `tools/update-wordpress.sh` bumps the
|
||||
pin, reapplies the series with fuzz, and tells you exactly which hunk needs a
|
||||
human if one does. [docs/upstream-merges.md](docs/upstream-merges.md) covers
|
||||
the procedure and how to switch to a vendored subtree if you would rather.
|
||||
Upstream releases arrive through `git subtree merge` against a branch of
|
||||
pristine imports, which three-way merges them against the fork's own commit
|
||||
on top. `tools/update-wordpress.sh <version>` does the whole thing;
|
||||
`patches/` keeps a generated, readable record of the 75 lines that differ
|
||||
from stock WordPress, so nobody has to read a 3,800-file log to find out what
|
||||
this fork changes in core.
|
||||
|
||||
The trade is repository size — WordPress is about 149 MB. Worth it for a fork
|
||||
that can absorb a security release in a minute.
|
||||
[docs/upstream-merges.md](docs/upstream-merges.md) has the procedure.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ WP_DEBUG=false
|
|||
# It is not the phrase itself and is useless without the database.
|
||||
SIRIUS_PRESS_KEY=
|
||||
|
||||
# --- core pin ---------------------------------------------------------------
|
||||
# Mirrors tools/wordpress.lock. Change both together, never just one.
|
||||
WP_VERSION=7.1.1
|
||||
WP_URL=https://wordpress.org/wordpress-7.1.1.tar.gz
|
||||
WP_SHA256=3996fee13448ef12e07e9f0c77db2f655ffa1b7cde71c80a4965d3bf1fb956b3
|
||||
# WordPress itself is vendored in the repository (wordpress/) and baked into
|
||||
# the image, so there is no version or checksum to configure here. See
|
||||
# docs/upstream-merges.md for how a new upstream release gets in.
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
# Sirius Press — PHP-FPM image with a verified, patched WordPress baked in.
|
||||
# Sirius Press — PHP-FPM image with the patched WordPress baked in.
|
||||
#
|
||||
# The image builds core rather than inheriting the official `wordpress` image
|
||||
# on purpose. That image ships whatever WordPress version it was tagged with,
|
||||
# and the patch series here is pinned to an exact one; silently applying a
|
||||
# fork's patches to a different core is how a setup wizard ends up half
|
||||
# rewritten. Downloading the pinned tarball and checking its hash during the
|
||||
# build makes the version an explicit, verifiable property of the image.
|
||||
# Core comes from this repository's `wordpress/` subtree, not from a download
|
||||
# and not from the official `wordpress` image. That image ships whatever
|
||||
# version it was tagged with, and the fork's core patch is pinned to an exact
|
||||
# one; applying a fork's patch to a different core is how a setup wizard ends
|
||||
# up half rewritten. Copying the vendored tree makes the image contain exactly
|
||||
# what `git log wordpress/` describes, with nothing fetched at build time.
|
||||
#
|
||||
# Core is installed to /opt/sirius-press/core, not to the document root. The
|
||||
# Core is staged at /opt/sirius-press/core, not at the document root. The
|
||||
# entrypoint copies it into place on every start, which is what makes
|
||||
# `docker compose build --pull && up -d` a real upgrade: the usual layout,
|
||||
# where the document root is itself a volume, pins core to whatever version
|
||||
|
|
@ -20,14 +20,10 @@
|
|||
|
||||
FROM php:8.3-fpm-bookworm
|
||||
|
||||
ARG WP_VERSION
|
||||
ARG WP_URL
|
||||
ARG WP_SHA256
|
||||
|
||||
RUN set -eux; \
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
ca-certificates curl patch \
|
||||
ca-certificates curl \
|
||||
libfreetype6-dev libjpeg62-turbo-dev libpng-dev libwebp-dev \
|
||||
libzip-dev libgmp-dev libicu-dev \
|
||||
; \
|
||||
|
|
@ -49,29 +45,24 @@ RUN { \
|
|||
echo 'expose_php = Off'; \
|
||||
} > /usr/local/etc/php/conf.d/sirius-press.ini
|
||||
|
||||
# --- core, verified -----------------------------------------------------------
|
||||
# --- core, from the subtree --------------------------------------------------
|
||||
|
||||
COPY wordpress/ /opt/sirius-press/core/
|
||||
|
||||
RUN set -eux; \
|
||||
curl -fsSL -o /tmp/wp.tar.gz "$WP_URL"; \
|
||||
echo "$WP_SHA256 /tmp/wp.tar.gz" | sha256sum -c -; \
|
||||
mkdir -p /opt/sirius-press; \
|
||||
tar -xzf /tmp/wp.tar.gz -C /tmp; \
|
||||
mv /tmp/wordpress /opt/sirius-press/core; \
|
||||
rm -rf /tmp/wp.tar.gz
|
||||
test -f /opt/sirius-press/core/wp-includes/version.php; \
|
||||
sed -n "s/.*wp_version = '\\(.*\\)'.*/\\1/p" \
|
||||
/opt/sirius-press/core/wp-includes/version.php \
|
||||
> /opt/sirius-press/core/.sirius-core-version; \
|
||||
echo "vendored WordPress $(cat /opt/sirius-press/core/.sirius-core-version)"
|
||||
|
||||
# --- the fork -----------------------------------------------------------------
|
||||
#
|
||||
# The patch is already applied in the subtree, so there is nothing to patch
|
||||
# here. patches/ is carried for auditing, not for building.
|
||||
|
||||
WORKDIR /opt/sirius-press/core
|
||||
|
||||
COPY patches/ /tmp/patches/
|
||||
RUN set -eux; \
|
||||
for p in /tmp/patches/*.patch; do \
|
||||
patch -p1 -F3 --forward --silent < "$p" \
|
||||
|| { echo "patch $p did not apply to WordPress $WP_VERSION"; exit 1; }; \
|
||||
done; \
|
||||
rm -rf /tmp/patches; \
|
||||
echo "$WP_VERSION" > /opt/sirius-press/core/.sirius-core-version
|
||||
|
||||
COPY plugins/ /opt/sirius-press/core/wp-content/plugins/
|
||||
COPY mu-plugins/ /opt/sirius-press/core/wp-content/mu-plugins/
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@
|
|||
# Three containers: MariaDB, PHP-FPM with the patched WordPress baked in, and
|
||||
# nginx in front. Only nginx is published.
|
||||
#
|
||||
# The volume layout is the part worth reading. WordPress core lives in the
|
||||
# image, not in a volume, so `docker compose build --pull && up -d` genuinely
|
||||
# upgrades it — the usual arrangement, where the whole document root is a
|
||||
# The volume layout is the part worth reading. WordPress core comes from the
|
||||
# repository's `wordpress/` subtree, is baked into the image, and is refilled
|
||||
# into the document root on every start — so `docker compose build && up -d`
|
||||
# genuinely upgrades it — the usual arrangement, where the whole document root is a
|
||||
# volume, freezes core at whatever version first created the volume and turns
|
||||
# every security release into a manual migration. What people actually need to
|
||||
# keep — uploads, plugins and themes they installed, and wp-config.php — is
|
||||
|
|
@ -43,13 +44,6 @@ services:
|
|||
build:
|
||||
context: ..
|
||||
dockerfile: docker/Dockerfile
|
||||
args:
|
||||
# install.sh copies these out of tools/wordpress.lock into .env.
|
||||
# Defaults are pinned here too, so a plain `docker compose build`
|
||||
# cannot quietly drift onto a different core.
|
||||
WP_VERSION: ${WP_VERSION:-7.1.1}
|
||||
WP_URL: ${WP_URL:-https://wordpress.org/wordpress-7.1.1.tar.gz}
|
||||
WP_SHA256: ${WP_SHA256:-3996fee13448ef12e07e9f0c77db2f655ffa1b7cde71c80a4965d3bf1fb956b3}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
db:
|
||||
|
|
|
|||
|
|
@ -70,9 +70,9 @@ faster and signature verification sits on the login path.
|
|||
tools/build.sh --zip
|
||||
```
|
||||
|
||||
Downloads the pinned WordPress, verifies its SHA-256, applies `patches/`, adds
|
||||
the plugins, and writes `dist/sirius-press-<version>.zip` alongside its
|
||||
checksum.
|
||||
Copies the vendored WordPress out of `wordpress/`, adds the plugins, and
|
||||
writes `dist/sirius-press-<version>.zip` alongside its checksum. Nothing is
|
||||
downloaded — core is in the repository.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -129,9 +129,9 @@ git pull
|
|||
cd docker && docker compose build && docker compose up -d
|
||||
```
|
||||
|
||||
Core, the fork's plugins and the patch series all come from the image, so this
|
||||
upgrades all three. Your uploads, your database, your other plugins and themes,
|
||||
and `wp-config.php` live in volumes and are untouched.
|
||||
Core and the fork's plugins both come from the image, so this upgrades both.
|
||||
Your uploads, your database, your other plugins and themes, and
|
||||
`wp-config.php` live in volumes and are untouched.
|
||||
|
||||
This is why the document root is refilled from the image on every start rather
|
||||
than being a volume of its own — the usual WordPress-in-Docker layout pins core
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ built-in server plus the official SQLite drop-in is enough, and it starts in
|
|||
seconds.
|
||||
|
||||
```bash
|
||||
# 1. a patched tree
|
||||
# 1. a complete tree (copied out of the vendored wordpress/, plugins added)
|
||||
tools/build.sh
|
||||
cp -R dist/sirius-press /tmp/wpsite
|
||||
|
||||
|
|
|
|||
|
|
@ -7,35 +7,33 @@ a liability rather than a project. This page is how Sirius Press takes them.
|
|||
|
||||
## The arrangement
|
||||
|
||||
WordPress is not in this repository. Instead:
|
||||
WordPress lives in this repository, at `wordpress/`, as a **git subtree**. The
|
||||
fork's own change sits on top of it as an ordinary commit.
|
||||
|
||||
- `tools/wordpress.lock` pins an exact version, its download URL and its
|
||||
SHA-256.
|
||||
- `patches/` holds the fork's core diff as a patch series.
|
||||
- `tools/build.sh` and the Docker image each download the pinned tarball,
|
||||
verify the hash, and apply the series.
|
||||
Three pieces make that work:
|
||||
|
||||
The entire core diff is currently **one file, 75 lines**: the setup wizard, at
|
||||
`wp-admin/install.php`. Everything else the fork does is plugins and hooks.
|
||||
| | |
|
||||
|---|---|
|
||||
| `wordpress/` | The vendored tree, patched. This is what gets built and shipped. |
|
||||
| `sirius-press/wordpress-upstream` | A branch holding **pristine** upstream releases, one commit each, never edited. The other side of the merge. |
|
||||
| `patches/` | A readable record of what the fork changes in core. Generated, not maintained. |
|
||||
|
||||
### Why not a vendored subtree
|
||||
The entire core diff is **one file, 75 lines**: `wp-admin/install.php`, the
|
||||
setup wizard. Everything else Sirius Press does is plugins and hooks.
|
||||
|
||||
The original plan was to vendor core as a `git subtree`, which is the standard
|
||||
way to run a fork with a substantial diff. Two numbers argued against it.
|
||||
### Why a subtree and not a patch series
|
||||
|
||||
WordPress 7.1.1 is **149 MB and 5,008 files**. The fork's core diff is **75
|
||||
lines**. Carrying the first to express the second means every clone, every
|
||||
`git status`, every `git subtree split` in the parent monorepo pays for a patch
|
||||
you can read in a minute — and it buries that patch in a haystack where nobody
|
||||
will ever review it again.
|
||||
Because a three-way merge understands something a patch does not. When
|
||||
upstream edits lines near the fork's change, `git subtree merge` merges them
|
||||
and moves on; `patch` either applies with fuzz and hopes, or fails and hands
|
||||
you the job of re-deriving the change by hand. A conflict from the merge is
|
||||
resolved once, in the file, and stays resolved — the next release merges
|
||||
against the resolution.
|
||||
|
||||
A patch series makes the opposite trade. The core change is a file you can read
|
||||
in one sitting, review in a pull request, and re-read whenever it stops
|
||||
applying. The cost is that upstream merges are `patch` rather than a three-way
|
||||
git merge — which, for 75 lines in one file, is not much of a cost.
|
||||
|
||||
This holds as long as the diff stays small. If the fork ever needs to change
|
||||
core substantially, vendor it properly: see "Switching to a subtree" below.
|
||||
The cost is repository size: WordPress is about 149 MB and 3,800 files. That
|
||||
is the price of a fork that can take a security release in a minute, and it is
|
||||
the right trade for a project whose whole argument is that it should outlive
|
||||
its maintainers' attention.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -45,46 +43,33 @@ core substantially, vendor it properly: see "Switching to a subtree" below.
|
|||
tools/update-wordpress.sh 7.1.2
|
||||
```
|
||||
|
||||
It fetches the release, verifies its SHA-1 against what wordpress.org
|
||||
publishes, records a SHA-256, applies the patch series to the new tree, and
|
||||
reports what happened.
|
||||
It downloads the release, checks it against the SHA-1 wordpress.org publishes,
|
||||
imports the pristine tree onto `sirius-press/wordpress-upstream`, and merges
|
||||
that branch into `wordpress/`. Then it updates `tools/wordpress.lock` and
|
||||
regenerates `patches/`.
|
||||
|
||||
Three possible outcomes:
|
||||
Two outcomes.
|
||||
|
||||
**Clean.** The series applied. `tools/wordpress.lock` is updated, the tests
|
||||
run, and you commit the lock change. Usually thirty seconds of work.
|
||||
**Clean.** The merge went through. Run the tests, build, commit. Usually a
|
||||
minute of work.
|
||||
|
||||
**Applied with fuzz.** Upstream moved code near a hunk but not the hunk itself.
|
||||
The script says which hunk and by how many lines. Look at the result, then
|
||||
refresh the series so the next release starts from a clean base:
|
||||
**Conflicted.** Upstream changed the same lines the fork changes — in
|
||||
practice, `wp-admin/install.php`. Git leaves the conflict in the file:
|
||||
|
||||
```bash
|
||||
tools/update-wordpress.sh 7.1.2 --refresh
|
||||
git status
|
||||
$EDITOR wordpress/wp-admin/install.php
|
||||
git add wordpress/wp-admin/install.php
|
||||
git commit
|
||||
tools/refresh-patches.sh
|
||||
```
|
||||
|
||||
**Failed.** Upstream rewrote the code the patch touches. This is the case that
|
||||
needs a person: open the new `wp-admin/install.php`, redo the change by hand,
|
||||
and regenerate the patch. The script leaves the unpacked tree in
|
||||
`dist/.upstream/` so there is something to work in.
|
||||
Then set `WP_VERSION`, `WP_URL`, `WP_SHA256` and `WP_SHA1` in
|
||||
`tools/wordpress.lock` by hand, since the script stopped before it got there.
|
||||
|
||||
In every case the fork is **not broken while you work** — the lock file still
|
||||
points at the last known-good version, and builds keep producing that until you
|
||||
change it.
|
||||
|
||||
---
|
||||
|
||||
## Reviewing a release before taking it
|
||||
|
||||
Security releases are usually small, and it is worth knowing what changed near
|
||||
the code the fork patches:
|
||||
|
||||
```bash
|
||||
tools/update-wordpress.sh 7.1.2 --diff wp-admin/install.php
|
||||
```
|
||||
|
||||
prints upstream's own diff for that file between the pinned version and the new
|
||||
one. If it is empty — which it usually is — the patch will apply and there is
|
||||
nothing to think about.
|
||||
Either way the fork is **not broken while you work**: the merge is in your
|
||||
working tree, and until you commit it, `wordpress/` still holds the last
|
||||
version that worked.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -92,42 +77,58 @@ nothing to think about.
|
|||
|
||||
```bash
|
||||
tests/run.sh
|
||||
```
|
||||
|
||||
The suite does not test core, but it does test every assumption the fork makes
|
||||
about it. Then build and try an actual install:
|
||||
|
||||
```bash
|
||||
tools/build.sh
|
||||
cd docker && docker compose build && docker compose up -d
|
||||
```
|
||||
|
||||
and walk through `wp-admin/install.php` once. The setup wizard is the only
|
||||
patched file, so it is the only thing an upstream change can break in a way
|
||||
the tests would miss.
|
||||
The suite does not test core, but it tests every assumption the fork makes
|
||||
about it. Then walk through `wp-admin/install.php` once in a browser — the
|
||||
setup wizard is the only patched file, so it is the only thing an upstream
|
||||
change can break in a way the tests would miss.
|
||||
[testing.md](testing.md) has a recipe for a throwaway instance that needs no
|
||||
database server.
|
||||
|
||||
---
|
||||
|
||||
## Switching to a subtree
|
||||
## Keeping `patches/` honest
|
||||
|
||||
If the diff ever grows past what a patch series is comfortable with, the
|
||||
mechanics are:
|
||||
`patches/` is documentation. It answers the question anyone auditing this 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.
|
||||
|
||||
It is generated from the tree, never edited:
|
||||
|
||||
```bash
|
||||
git remote add wordpress https://github.com/WordPress/WordPress.git
|
||||
git fetch --depth=1 wordpress 7.1.1
|
||||
git subtree add --prefix=wordpress FETCH_HEAD --squash
|
||||
tools/refresh-patches.sh # rewrite it
|
||||
tools/refresh-patches.sh --check # fail if it has drifted (for CI)
|
||||
```
|
||||
|
||||
and then, per release:
|
||||
Generated documentation stays true. A hand-maintained record of a fork's core
|
||||
diff drifts, and a stale one is worse than none, because people trust it.
|
||||
|
||||
---
|
||||
|
||||
## Changing core yourself
|
||||
|
||||
Edit the file under `wordpress/` and commit it like any other change. The next
|
||||
upstream merge will three-way it.
|
||||
|
||||
Before you do: check whether a plugin hook can carry the change instead. Every
|
||||
line added to `wordpress/` is a line that can conflict with upstream forever,
|
||||
and the reason this fork's merges are cheap is that there are only 75 of them.
|
||||
The registration form, the password-reset page and the mail pipeline were all
|
||||
replaced from plugins precisely so they would never appear in this directory.
|
||||
|
||||
---
|
||||
|
||||
## If the upstream branch is missing
|
||||
|
||||
A clone made with `--single-branch` will not have
|
||||
`sirius-press/wordpress-upstream`, and `tools/update-wordpress.sh` will say so
|
||||
rather than guessing. Fetch it:
|
||||
|
||||
```bash
|
||||
git fetch --depth=1 wordpress 7.1.2
|
||||
git subtree merge --prefix=wordpress FETCH_HEAD --squash
|
||||
git fetch origin sirius-press/wordpress-upstream:sirius-press/wordpress-upstream
|
||||
```
|
||||
|
||||
with `patches/` becoming the record of what was changed rather than the
|
||||
mechanism that changes it. The build script would then copy `wordpress/`
|
||||
instead of downloading and patching.
|
||||
|
||||
Worth doing when the core diff reaches, say, a dozen files. Not before.
|
||||
Building and running do not need it — only taking a new upstream release does.
|
||||
|
|
|
|||
|
|
@ -1,31 +1,13 @@
|
|||
Subject: [PATCH] setup wizard: ask for a wallet, not a mailbox
|
||||
Subject: [PATCH] wp-admin/install.php
|
||||
|
||||
The installer is the one place in WordPress where the fork cannot do its
|
||||
work from a plugin. It runs before plugins load, and it refuses to finish
|
||||
without an email address, so a site with no mail identity cannot be
|
||||
installed at all.
|
||||
|
||||
The change is the smallest one that removes the requirement:
|
||||
|
||||
- "Your Email" becomes "Your wallet address", and it is optional. The
|
||||
installer has nothing to verify a signature against yet — the site
|
||||
does not exist — so an address typed here is taken on trust and can be
|
||||
replaced from the profile screen afterwards, where it CAN be proved.
|
||||
- The two is_email() gates become one address check.
|
||||
- wp_install() still receives an email string, because its signature and
|
||||
everything downstream of it expects one. It gets a permanently
|
||||
unroutable .invalid placeholder.
|
||||
|
||||
The two helper functions are defined by the Sirius Press bootstrap
|
||||
must-use plugin, which loads before this file on every request including
|
||||
the installer. If that plugin is missing, they fall back to accepting
|
||||
nothing and the installer behaves as it does on stock WordPress minus the
|
||||
email field.
|
||||
The fork's change to this file, regenerated by tools/refresh-patches.sh.
|
||||
It is a record, not the mechanism: core is vendored under wordpress/ and
|
||||
this diff is what distinguishes it from pristine upstream.
|
||||
|
||||
Applies to: WordPress 7.1.1
|
||||
--- a/wp-admin/install.php
|
||||
+++ b/wp-admin/install.php
|
||||
@@ -101,6 +101,8 @@
|
||||
@@ -101,6 +101,8 @@ function display_setup_form( $error = null ) {
|
||||
$weblog_title = isset( $_POST['weblog_title'] ) ? trim( wp_unslash( $_POST['weblog_title'] ) ) : '';
|
||||
$user_name = isset( $_POST['user_name'] ) ? trim( wp_unslash( $_POST['user_name'] ) ) : '';
|
||||
$admin_email = isset( $_POST['admin_email'] ) ? trim( wp_unslash( $_POST['admin_email'] ) ) : '';
|
||||
|
|
@ -34,7 +16,7 @@ Applies to: WordPress 7.1.1
|
|||
|
||||
if ( ! is_null( $error ) ) {
|
||||
?>
|
||||
@@ -175,9 +177,9 @@
|
||||
@@ -175,9 +177,9 @@ function display_setup_form( $error = null ) {
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<tr>
|
||||
|
|
@ -47,7 +29,7 @@ Applies to: WordPress 7.1.1
|
|||
</tr>
|
||||
<?php $blog_privacy_selector_title = has_action( 'blog_privacy_selector' ) ? __( 'Site visibility' ) : __( 'Search engine visibility' ); ?>
|
||||
<tr>
|
||||
@@ -411,10 +413,20 @@
|
||||
@@ -411,10 +413,20 @@ switch ( $step ) {
|
||||
$user_name = isset( $_POST['user_name'] ) ? trim( wp_unslash( $_POST['user_name'] ) ) : '';
|
||||
$admin_password = isset( $_POST['admin_password'] ) ? wp_unslash( $_POST['admin_password'] ) : '';
|
||||
$admin_password_check = isset( $_POST['admin_password2'] ) ? wp_unslash( $_POST['admin_password2'] ) : '';
|
||||
|
|
@ -70,7 +52,7 @@ Applies to: WordPress 7.1.1
|
|||
$error = false;
|
||||
if ( empty( $user_name ) ) {
|
||||
// TODO: Poka-yoke.
|
||||
@@ -427,19 +439,20 @@
|
||||
@@ -427,19 +439,20 @@ switch ( $step ) {
|
||||
// TODO: Poka-yoke.
|
||||
display_setup_form( __( 'Your passwords do not match. Please try again.' ) );
|
||||
$error = true;
|
||||
20
tests/run.sh
20
tests/run.sh
|
|
@ -39,14 +39,28 @@ fi
|
|||
bar "syntax"
|
||||
syntax_ok=1
|
||||
if command -v "$PHP_BIN" >/dev/null 2>&1; then
|
||||
# The fork's own PHP, plus every core file the fork patches. Sweeping all
|
||||
# of wordpress/ would lint 3,800 files of upstream code that upstream
|
||||
# already tests, and turn a one-second suite into a minute of waiting.
|
||||
lint_targets() {
|
||||
find "$here/../plugins" "$here/../mu-plugins" "$here" \
|
||||
-name '*.php' -not -path '*/node_modules/*' 2>/dev/null
|
||||
for patch in "$here"/../patches/*.patch; do
|
||||
[ -e "$patch" ] || continue
|
||||
sed -n 's|^--- a/||p' "$patch" | while IFS= read -r rel; do
|
||||
case "$rel" in *.php) echo "$here/../wordpress/$rel" ;; esac
|
||||
done
|
||||
done
|
||||
}
|
||||
while IFS= read -r file; do
|
||||
[ -f "$file" ] || continue
|
||||
if ! "$PHP_BIN" -l "$file" >/dev/null 2>&1; then
|
||||
echo " FAIL $file"
|
||||
"$PHP_BIN" -l "$file" 2>&1 | head -3
|
||||
syntax_ok=0
|
||||
status=1
|
||||
fi
|
||||
done < <(find "$here/.." -name '*.php' -not -path '*/dist/*' -not -path '*/node_modules/*')
|
||||
done < <(lint_targets)
|
||||
fi
|
||||
if command -v "$NODE_BIN" >/dev/null 2>&1; then
|
||||
while IFS= read -r file; do
|
||||
|
|
@ -55,9 +69,9 @@ if command -v "$NODE_BIN" >/dev/null 2>&1; then
|
|||
syntax_ok=0
|
||||
status=1
|
||||
fi
|
||||
done < <(find "$here/.." -name '*.js' -not -path '*/dist/*' -not -path '*/node_modules/*')
|
||||
done < <(find "$here/../plugins" "$here" -name '*.js' -not -path '*/node_modules/*' 2>/dev/null)
|
||||
fi
|
||||
[ "$syntax_ok" -eq 1 ] && echo " ok every PHP and JS file parses"
|
||||
[ "$syntax_ok" -eq 1 ] && echo " ok the fork's PHP and JS parses, including every patched core file"
|
||||
|
||||
echo
|
||||
if [ "$status" -eq 0 ]; then
|
||||
|
|
|
|||
|
|
@ -1,18 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
# build.sh — assemble a complete, patched Sirius Press tree.
|
||||
# build.sh — assemble a complete Sirius Press tree.
|
||||
#
|
||||
# Downloads the pinned WordPress, verifies it against the checksum in
|
||||
# tools/wordpress.lock, applies the patch series in patches/, drops this
|
||||
# repository's plugins and must-use plugins into place, and leaves the result
|
||||
# in dist/sirius-press/.
|
||||
# Copies the vendored WordPress from wordpress/, drops this repository's
|
||||
# plugins and must-use plugins into it, and leaves the result in
|
||||
# dist/sirius-press/.
|
||||
#
|
||||
# With --zip it also produces dist/sirius-press-<version>.zip, which is the
|
||||
# artifact shared-hosting users upload.
|
||||
#
|
||||
# The verification is not a formality. This script fetches executable code
|
||||
# over the network and then runs it as a web server; the checksum is the only
|
||||
# thing standing between a compromised mirror and every site built from it.
|
||||
# If it fails, the build stops — there is no --skip-verify, on purpose.
|
||||
# There is no download and no checksum step, because there is nothing to
|
||||
# fetch: core is in the repository, already patched, and what you build is
|
||||
# exactly what you can read in `git log wordpress/`. Moving to a new upstream
|
||||
# release is tools/update-wordpress.sh, not a flag here.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
|
|
@ -25,7 +24,7 @@ source tools/wordpress.lock
|
|||
VERSION="$(grep -m1 "^ \* Version:" plugins/sirius-press-core/sirius-press-core.php | awk '{print $3}')"
|
||||
DIST="$here/dist"
|
||||
TARGET="$DIST/sirius-press"
|
||||
CACHE="${SIRIUS_BUILD_CACHE:-$DIST/.cache}"
|
||||
SOURCE="$here/wordpress"
|
||||
MAKE_ZIP=0
|
||||
|
||||
for arg in "$@"; do
|
||||
|
|
@ -38,67 +37,22 @@ done
|
|||
say() { printf '\033[1m→\033[0m %s\n' "$*"; }
|
||||
die() { printf '\033[31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
command -v curl >/dev/null || die "curl is required"
|
||||
command -v tar >/dev/null || die "tar is required"
|
||||
command -v patch >/dev/null || die "patch is required (used to apply the core patch series)"
|
||||
[ -f "$SOURCE/wp-includes/version.php" ] \
|
||||
|| die "wordpress/ is missing or empty — check the whole repository was cloned."
|
||||
|
||||
# ---------------------------------------------------------------- fetch core
|
||||
|
||||
mkdir -p "$CACHE"
|
||||
tarball="$CACHE/wordpress-$WP_VERSION.tar.gz"
|
||||
|
||||
if [ ! -f "$tarball" ]; then
|
||||
say "downloading WordPress $WP_VERSION"
|
||||
curl -fsSL -o "$tarball.part" "$WP_URL" || die "download failed"
|
||||
mv "$tarball.part" "$tarball"
|
||||
vendored="$(grep -m1 'wp_version = ' "$SOURCE/wp-includes/version.php" | sed "s/.*'\(.*\)'.*/\1/")"
|
||||
if [ "$vendored" != "$WP_VERSION" ]; then
|
||||
die "wordpress/ holds $vendored but tools/wordpress.lock says $WP_VERSION.
|
||||
One of them is stale; tools/update-wordpress.sh keeps them in step."
|
||||
fi
|
||||
|
||||
say "verifying checksum"
|
||||
actual="$(sha256sum "$tarball" | cut -d' ' -f1)"
|
||||
if [ "$actual" != "$WP_SHA256" ]; then
|
||||
rm -f "$tarball"
|
||||
die "checksum mismatch for WordPress $WP_VERSION
|
||||
expected $WP_SHA256
|
||||
got $actual
|
||||
The cached download has been deleted. If this repeats, the mirror is serving
|
||||
something other than what this fork was built against — do not work around it."
|
||||
fi
|
||||
# ------------------------------------------------------------------ assemble
|
||||
|
||||
# --------------------------------------------------------------- assemble
|
||||
|
||||
say "unpacking into dist/sirius-press"
|
||||
say "copying WordPress $vendored out of wordpress/"
|
||||
rm -rf "$TARGET"
|
||||
mkdir -p "$TARGET"
|
||||
tar -xzf "$tarball" -C "$DIST"
|
||||
mv "$DIST/wordpress"/* "$TARGET"/
|
||||
mv "$DIST/wordpress"/.[!.]* "$TARGET"/ 2>/dev/null || true
|
||||
rmdir "$DIST/wordpress"
|
||||
|
||||
# ------------------------------------------------------------ patch series
|
||||
|
||||
shopt -s nullglob
|
||||
patches=(patches/*.patch)
|
||||
shopt -u nullglob
|
||||
|
||||
if [ ${#patches[@]} -eq 0 ]; then
|
||||
say "no core patches to apply"
|
||||
else
|
||||
say "applying ${#patches[@]} core patch(es)"
|
||||
for patch in "${patches[@]}"; do
|
||||
# -F3 tolerates a few lines of drift around the hunk, so a WordPress
|
||||
# point release that shifts the surrounding code still takes the patch.
|
||||
# If it genuinely no longer fits, stop: a half-patched installer is
|
||||
# worse than a failed build.
|
||||
if (cd "$TARGET" && patch -p1 -F3 --forward --silent < "$here/$patch"); then
|
||||
echo " ok $(basename "$patch")"
|
||||
else
|
||||
die "$(basename "$patch") did not apply to WordPress $WP_VERSION.
|
||||
Run tools/update-wordpress.sh to refresh the series against this version."
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------- our code
|
||||
# The trailing /. copies the contents rather than nesting another directory.
|
||||
cp -a "$SOURCE/." "$TARGET/"
|
||||
|
||||
say "installing Sirius Press plugins"
|
||||
mkdir -p "$TARGET/wp-content/plugins" "$TARGET/wp-content/mu-plugins"
|
||||
|
|
@ -107,13 +61,6 @@ for plugin in plugins/*/; do
|
|||
done
|
||||
cp mu-plugins/*.php "$TARGET/wp-content/mu-plugins/"
|
||||
|
||||
# The stock wp-config-sample.php has no SIRIUS_PRESS_KEY, and a site that
|
||||
# never sets one falls back to its auth salts — which works, but means
|
||||
# rotating salts orphans the stored publishing key.
|
||||
if [ -f docker/wp-config-sirius.php ]; then
|
||||
cp docker/wp-config-sirius.php "$TARGET/wp-config-sirius-sample.php"
|
||||
fi
|
||||
|
||||
say "built dist/sirius-press ($(du -sh "$TARGET" | cut -f1))"
|
||||
|
||||
# --------------------------------------------------------------------- zip
|
||||
|
|
@ -151,9 +98,9 @@ fi
|
|||
|
||||
cat <<EOF
|
||||
|
||||
Sirius Press $VERSION, built on WordPress $WP_VERSION.
|
||||
Sirius Press $VERSION, on WordPress $vendored.
|
||||
|
||||
dist/sirius-press/ a complete, patched WordPress tree
|
||||
dist/sirius-press/ a complete tree, ready to serve
|
||||
$( [ "$MAKE_ZIP" -eq 1 ] && echo " dist/sirius-press-$VERSION.zip upload this to a shared host" )
|
||||
|
||||
To run it locally: cd docker && docker compose up -d
|
||||
|
|
|
|||
107
tools/refresh-patches.sh
Normal file
107
tools/refresh-patches.sh
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
#!/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
|
||||
|
|
@ -1,51 +1,57 @@
|
|||
#!/usr/bin/env bash
|
||||
# update-wordpress.sh — move the fork onto a new WordPress release.
|
||||
# update-wordpress.sh — bring a new WordPress release into the fork.
|
||||
#
|
||||
# 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.
|
||||
# Two steps, and the second is the one that matters:
|
||||
#
|
||||
# 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.
|
||||
# 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)"
|
||||
cd "$here"
|
||||
repo="$(git -C "$here" rev-parse --show-toplevel)"
|
||||
prefix="${here#"$repo"/}/wordpress"
|
||||
|
||||
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>]"
|
||||
[ -n "$VERSION" ] || die "usage: tools/update-wordpress.sh <version>"
|
||||
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]] || die "'$VERSION' does not look like a WordPress version"
|
||||
|
||||
# shellcheck source=wordpress.lock
|
||||
source tools/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
|
||||
|
||||
WORK="$here/dist/.upstream"
|
||||
CACHE="$here/dist/.cache"
|
||||
mkdir -p "$WORK" "$CACHE"
|
||||
|
||||
mkdir -p "$CACHE"
|
||||
URL="https://wordpress.org/wordpress-${VERSION}.tar.gz"
|
||||
TARBALL="$CACHE/wordpress-${VERSION}.tar.gz"
|
||||
|
||||
|
|
@ -57,155 +63,133 @@ if [ ! -f "$TARBALL" ]; then
|
|||
mv "$TARBALL.part" "$TARBALL"
|
||||
fi
|
||||
|
||||
say "verifying against wordpress.org's published SHA-1"
|
||||
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 did not serve a .sha1 for this release; continuing on the SHA-256 recorded below"
|
||||
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 does not match what wordpress.org publishes.
|
||||
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)"
|
||||
|
||||
# ------------------------------------------------------------------ unpack
|
||||
# ------------------------------------------- import onto the upstream branch
|
||||
|
||||
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"
|
||||
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"
|
||||
|
||||
# --------------------------------------------------------- what changed?
|
||||
cleanup() {
|
||||
git -C "$repo" worktree remove --force "$WORKTREE" >/dev/null 2>&1 || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
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
|
||||
# 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
|
||||
|
||||
# ------------------------------------------------------------ the series
|
||||
git -C "$WORKTREE" \
|
||||
-c user.name="Silent Mode" -c user.email="hephaestus@silentmode.st" \
|
||||
commit -q -m "WordPress ${VERSION}
|
||||
|
||||
shopt -s nullglob
|
||||
patches=(patches/*.patch)
|
||||
shopt -u nullglob
|
||||
Pristine upstream, unpacked from the official wordpress.org tarball.
|
||||
|
||||
failed=0
|
||||
fuzzed=0
|
||||
${URL}
|
||||
sha1 ${actual_sha1} (published by wordpress.org)
|
||||
sha256 ${NEW_SHA256}
|
||||
|
||||
if [ ${#patches[@]} -eq 0 ]; then
|
||||
say "no patches to apply"
|
||||
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
|
||||
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
|
||||
merged=0
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
if [ "$failed" -eq 1 ]; then
|
||||
if [ "$merged" -eq 0 ]; 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.
|
||||
$(printf '\033[31mThe merge stopped on a conflict.\033[0m')
|
||||
|
||||
Upstream changed code the fork also changes — almost certainly
|
||||
wp-admin/install.php, the only file this fork patches.
|
||||
|
||||
git status # what conflicted
|
||||
git diff # the overlap
|
||||
\$EDITOR ${prefix}/wp-admin/install.php
|
||||
git add ${prefix}/wp-admin/install.php
|
||||
git commit # finish the merge
|
||||
|
||||
Then regenerate the readable copy of the diff and update the lock:
|
||||
|
||||
tools/refresh-patches.sh
|
||||
# set WP_VERSION / WP_URL / WP_SHA256 / WP_SHA1 in tools/wordpress.lock
|
||||
|
||||
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'
|
||||
python3 - "$VERSION" "$URL" "$NEW_SHA256" "$actual_sha1" "$here/tools/wordpress.lock" <<'PY'
|
||||
import io, sys
|
||||
version, url, sha256, sha1 = sys.argv[1:5]
|
||||
path = 'tools/wordpress.lock'
|
||||
version, url, sha256, sha1, path = sys.argv[1:6]
|
||||
fields = {
|
||||
'WP_VERSION=': version,
|
||||
'WP_URL=': url,
|
||||
'WP_SHA256=': sha256,
|
||||
'WP_SHA1=': sha1,
|
||||
}
|
||||
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:
|
||||
for key, value in fields.items():
|
||||
if line.startswith(key):
|
||||
line = f'{key}{value}\n'
|
||||
break
|
||||
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
|
||||
if [ -x "$here/tools/refresh-patches.sh" ]; then
|
||||
say "refreshing patches/ so it still describes the fork's core diff"
|
||||
"$here/tools/refresh-patches.sh" || warn "could not refresh patches/ — do it by hand"
|
||||
fi
|
||||
|
||||
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
|
||||
${CURRENT} -> ${VERSION}
|
||||
|
||||
The merge and the lock update are staged as commits already; patches/ may
|
||||
have changed too. Before pushing:
|
||||
|
||||
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.
|
||||
file this fork patches, so it is the only thing this can have broken.
|
||||
|
||||
EOF
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue