patchette

usage: show a STACK file and a patch file, right after the first export

commit d231dd14983383230e96559d78dc3ba686da3f8f · parent 271bda8865 · browse this tree
Ximianth, 2026-10-27 12:22:29 UTC

The guide showed the patches repo only through `ls` and, later, a diff;
a reader had to go elsewhere to see what the files themselves hold.
Now the first export's session is followed by docs-polish's STACK and
its first patch file, each as a plain block of its own, with a sentence
on what's in each, and a link to FORMAT.md for the full specification.

The files are outputs of that session's case, so they're checked and
regenerated like the sessions are.  The case gets its own rule,
`snapshot/session`, whose function names the two files; it runs after
the same `paired/prelude` as the other paired sessions.

docs-polish in the test corpus gains a second commit, so the STACK's
series shows more than one patch, and the evolving session's diff shows
one patch changing while the patch before it stays untouched.  The
first commit is unchanged, so the tests that edit it are unaffected.
diff --git a/docs/userguide/USAGE.md b/docs/userguide/USAGE.md
index df3e303..3c13e39 100644
--- a/docs/userguide/USAGE.md
+++ b/docs/userguide/USAGE.md
@@ -50,14 +50,15 @@ Taking snapshots
 Work on your branches however you like; then export them, and commit the result in the patches repo.
 Export takes the upstream commit your branches are based on, then the branches:
 
-[testmark]:# (paired/snapshotting/session)
+[testmark]:# (snapshot/session)
 ```
 ~/src/frob$ patchette export origin/main topic/fancy docs-polish
 export: wrote ~/src/frob-patches/topic¦fancy (8 patches)
-export: wrote ~/src/frob-patches/docs-polish (1 patches)
+export: wrote ~/src/frob-patches/docs-polish (2 patches)
 
 ~/src/frob$ ls ../frob-patches/docs-polish
 STACK
+mention-the-oiling-schedule.patch
 polish-the-readme.patch
 
 ~/src/frob$ git -C ../frob-patches add .
@@ -67,13 +68,53 @@ polish-the-readme.patch
 
 Each branch becomes a folder: a `STACK` file saying where it's based and what's in it, and one patch file per commit.
 
+`~/src/frob-patches/docs-polish/STACK` names the branch, the upstream commit it's based on, and its tip;
+then, after `series`, its patches, in order:
+
+[testmark]:# (snapshot/STACK)
+```
+ref refs/heads/docs-polish
+base 5b0130cfd2153bcdb4a6d7ec356e7d805018afc9
+tip 2dfecf1d7ce26028ef2dcc7430b5b9bc9c8aa86a
+series
+polish-the-readme
+mention-the-oiling-schedule
+```
+
+`~/src/frob-patches/docs-polish/polish-the-readme.patch` is one commit:
+its parents (`BASE` is the STACK's base), then the rest of its headers exactly as git stored them; its message, between `----` lines; and its diff:
+
+[testmark]:# (snapshot/polish-the-readme.patch)
+```
+parents BASE
+author Ada Downstream <ada@downstream.example> 1700000660 +0000
+committer Ada Downstream <ada@downstream.example> 1700000660 +0000
+
+----
+> Polish the readme
+----
+
+diff --git a/README.md b/README.md
+index a330cd687e7fdede54bbe0aca5df47c06d2e8b64..c195933372242cdbb3c014665ebcff2bb3fb4449 100644
+--- a/README.md
++++ b/README.md
+@@ -3,3 +3,5 @@
+ Upstream docs.
+ 
+ More upstream docs.
++
++Downstream notes: be kind to the machinery.
+```
+
+Both formats are specified in full in [FORMAT.md](../hacking/FORMAT.md).
+
 The payoff comes when your patches change.
 Here, a commit on `docs-polish` gets reworked; export again, and the patches repo shows what changed about the change:
 
 [testmark]:# (paired/evolving/session)
 ```
 ~/src/frob$ patchette export origin/main docs-polish
-export: wrote ~/src/frob-patches/docs-polish (1 patches)
+export: wrote ~/src/frob-patches/docs-polish (2 patches)
 
 ~/src/frob$ git -C ../frob-patches add .
 
@@ -81,51 +122,51 @@ export: wrote ~/src/frob-patches/docs-polish (1 patches)
 
 ~/src/frob$ git switch -q docs-polish
 
-~/src/frob$ sed -i 's/be kind to/be gentle with/' README.md
+~/src/frob$ sed -i 's/weekly/daily/' README.md
 
 ~/src/frob$ git commit -q -a --amend --no-edit
 
 ~/src/frob$ patchette export origin/main docs-polish
-export: wrote ~/src/frob-patches/docs-polish (1 patches)
+export: wrote ~/src/frob-patches/docs-polish (2 patches)
 
 ~/src/frob$ git -C ../frob-patches diff
 diff --git a/docs-polish/STACK b/docs-polish/STACK
-index d187142..eb8cce4 100644
+index c56f84d..99ac5cd 100644
 --- a/docs-polish/STACK
 +++ b/docs-polish/STACK
-@@ -1,5 +1,5 @@
+@@ -1,6 +1,6 @@
  ref refs/heads/docs-polish
  base 5b0130cfd2153bcdb4a6d7ec356e7d805018afc9
--tip 485a9d568a1be975c873793612c74733df10dd30
-+tip c8e5de76c06ca994c681de041257be8b01b28969
+-tip 2dfecf1d7ce26028ef2dcc7430b5b9bc9c8aa86a
++tip 88f146ae1801f5fd8d443d6eb5904f09b88927c6
  series
  polish-the-readme
-diff --git a/docs-polish/polish-the-readme.patch b/docs-polish/polish-the-readme.patch
-index 0373218..1cf464c 100644
---- a/docs-polish/polish-the-readme.patch
-+++ b/docs-polish/polish-the-readme.patch
-@@ -1,13 +1,13 @@
- parents BASE
- author Ada Downstream <ada@downstream.example> 1700000660 +0000
--committer Ada Downstream <ada@downstream.example> 1700000660 +0000
+ mention-the-oiling-schedule
+diff --git a/docs-polish/mention-the-oiling-schedule.patch b/docs-polish/mention-the-oiling-schedule.patch
+index 8b0dda3..1f6c371 100644
+--- a/docs-polish/mention-the-oiling-schedule.patch
++++ b/docs-polish/mention-the-oiling-schedule.patch
+@@ -1,17 +1,17 @@
+ parents polish-the-readme
+ author Ada Downstream <ada@downstream.example> 1700000720 +0000
+-committer Ada Downstream <ada@downstream.example> 1700000720 +0000
 +committer Ada Downstream <ada@downstream.example> 1700086400 +0000
  
  ----
- > Polish the readme
+ > Mention the oiling schedule
  ----
  
  diff --git a/README.md b/README.md
--index a330cd687e7fdede54bbe0aca5df47c06d2e8b64..c195933372242cdbb3c014665ebcff2bb3fb4449 100644
-+index a330cd687e7fdede54bbe0aca5df47c06d2e8b64..4487040f0eaebfa924f8b6011a62557137d3d03d 100644
+-index c195933372242cdbb3c014665ebcff2bb3fb4449..073a43988cb91f0fe493964670f6d52517082346 100644
++index c195933372242cdbb3c014665ebcff2bb3fb4449..61f9c849c8c9962d481e8ce3874abcc47a640eba 100644
  --- a/README.md
  +++ b/README.md
- @@ -3,3 +3,5 @@
-@@ -15,4 +15,4 @@ index a330cd687e7fdede54bbe0aca5df47c06d2e8b64..c195933372242cdbb3c014665ebcff2b
-  
+ @@ -5,3 +5,4 @@ Upstream docs.
   More upstream docs.
- +
--+Downstream notes: be kind to the machinery.
-++Downstream notes: be gentle with the machinery.
+  
+  Downstream notes: be kind to the machinery.
+-+Oil the gears weekly.
+++Oil the gears daily.
 ```
 
 Commit that with a message saying why it changed, and the history of your patches tells its own story.
@@ -142,10 +183,10 @@ Name branches to check just those:
 ```
 ~/src/frob$ patchette export origin/main topic/fancy docs-polish
 export: wrote ~/src/frob-patches/topic¦fancy (8 patches)
-export: wrote ~/src/frob-patches/docs-polish (1 patches)
+export: wrote ~/src/frob-patches/docs-polish (2 patches)
 
 ~/src/frob$ patchette verify
-verify: ok: refs/heads/docs-polish reproduces recorded tip 485a9d568a1be975c873793612c74733df10dd30
+verify: ok: refs/heads/docs-polish reproduces recorded tip 2dfecf1d7ce26028ef2dcc7430b5b9bc9c8aa86a
 verify: ok: refs/heads/topic/fancy reproduces recorded tip cc261dc9f0b878a78e2b80aeb60de397205f61ad
 
 ~/src/frob$ patchette verify topic/fancy
@@ -163,7 +204,7 @@ Pair the new clone, and import:
 ```
 ~/src/frob$ patchette export origin/main topic/fancy docs-polish
 export: wrote ~/src/frob-patches/topic¦fancy (8 patches)
-export: wrote ~/src/frob-patches/docs-polish (1 patches)
+export: wrote ~/src/frob-patches/docs-polish (2 patches)
 
 ~/src/frob$ cd ..
 
@@ -175,7 +216,7 @@ export: wrote ~/src/frob-patches/docs-polish (1 patches)
 paired: '~/src/frob2' -> patches dir '../frob-patches'
 
 ~/src/frob2$ patchette import
-import: created refs/heads/docs-polish at 485a9d568a1be975c873793612c74733df10dd30
+import: created refs/heads/docs-polish at 2dfecf1d7ce26028ef2dcc7430b5b9bc9c8aa86a
 import: created refs/heads/topic/fancy at cc261dc9f0b878a78e2b80aeb60de397205f61ad
 
 ~/src/frob2$ git rev-parse topic/fancy
@@ -245,10 +286,10 @@ each one, given, wins over the pairing.
 ~$ git init -q -b main src/frob-patches
 
 ~$ patchette export --subject=src/frob --patches=src/frob-patches origin/main docs-polish
-export: wrote ~/src/frob-patches/docs-polish (1 patches)
+export: wrote ~/src/frob-patches/docs-polish (2 patches)
 
 ~$ patchette verify --subject=src/frob --patches=src/frob-patches
-verify: ok: refs/heads/docs-polish reproduces recorded tip 485a9d568a1be975c873793612c74733df10dd30
+verify: ok: refs/heads/docs-polish reproduces recorded tip 2dfecf1d7ce26028ef2dcc7430b5b9bc9c8aa86a
 ```
 
 
@@ -277,14 +318,14 @@ patchette: --subject/--patches not given, and the cwd is not inside a git reposi
 paired: '~/src/frob' -> patches dir '../frob-patches'
 
 ~/src/frob$ patchette export origin/main docs-polish
-export: wrote ~/src/frob-patches/docs-polish (1 patches)
+export: wrote ~/src/frob-patches/docs-polish (2 patches)
 
 ~/src/frob$ patchette verify docs-polish --patches=../frob-patches
 patchette: no branch folder for '--patches=../frob-patches' in '~/src/frob-patches'
 [exit status: 1]
 
 ~/src/frob$ patchette verify --patches=
-verify: ok: refs/heads/docs-polish reproduces recorded tip 485a9d568a1be975c873793612c74733df10dd30
+verify: ok: refs/heads/docs-polish reproduces recorded tip 2dfecf1d7ce26028ef2dcc7430b5b9bc9c8aa86a
 
 ~/src/frob$ patchette export
 patchette: usage: patchette export [--sigil=quote|--sigil=tab] [--subject=<repo>] [--patches=<dir>] <base-rev> <branch>...
diff --git a/tests/lib.sh b/tests/lib.sh
index 32d53ce..49abc6a 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -130,7 +130,7 @@ tick() {
 ## a merge (with an in-range side branch), an extra commit header in the
 ## jj `change-id` style, an empty commit, a body with a blank line, and a
 ## message without a final newline.
-## `docs-polish` exists to make the layout's branch mapping visible.
+## `docs-polish` is the plain example: two ordinary commits, a short series.
 ## `odd-bytes` carries content that git config or attributes could perturb.
 ##
 ## - @param $1 output directory; created.  Gets `upstream/`, `dev/`, and a
@@ -222,12 +222,16 @@ make_corpus() (
 	new=$(git cat-file commit HEAD | head -c -1 | git hash-object -t commit -w --stdin)
 	git update-ref refs/heads/topic/fancy "$new"
 
-	# --- second branch, small on purpose ---
+	# --- second branch: the plain example ---
 	git switch -qc docs-polish main
 	printf '\nDownstream notes: be kind to the machinery.\n' >>README.md
 	git add -A
 	tick
 	git commit -q -m "Polish the readme"
+	printf 'Oil the gears weekly.\n' >>README.md
+	git add -A
+	tick
+	git commit -q -m "Mention the oiling schedule"
 
 	# --- third branch: content that git config or attributes could bite on ---
 	# Trailing whitespace, CRLF, binary, a non-ASCII path with a space, a
diff --git a/tests/test-usage.sh b/tests/test-usage.sh
index e6a975a..35e09bb 100755
--- a/tests/test-usage.sh
+++ b/tests/test-usage.sh
@@ -3,6 +3,7 @@
 ## is a terminal session: its prompt lines (`~/dir$ command`, or `/dir$ command`) are run in order, in a fresh sandbox,
 ## and the whole session as it ran -- prompts, commands, output -- must match the hunk.
 ## A `paired/NAME/session` starts after the doc's `paired/prelude` hunk has run; a `fresh/NAME/session` starts from the bare sandbox.
+## `snapshot/session` is a paired session that also shows two of the files it wrote.
 ## Run with TESTMARK_REGEN=1 to rewrite the sessions from what patchette does now; review with `git diff`.
 # No set -e up here: testmark-bash mis-reports failing cases under it.  Cases run under set -euo pipefail regardless.
 source "${TESTMARK_BASH:-$(dirname "${BASH_SOURCE[0]}")/../../../warplibs/testmark-bash}/lib/testmark.bash" || exit 1
@@ -96,7 +97,15 @@ exercise_paired() {
 	run_in_sandbox paired/prelude
 }
 
+## exercise_snapshot runs the first-export session, then shows two of the files it wrote, each as an output of its own.
+exercise_snapshot() {
+	run_in_sandbox paired/prelude
+	testcase_output STACK <"$HOME/src/frob-patches/docs-polish/STACK"
+	testcase_output polish-the-readme.patch <"$HOME/src/frob-patches/docs-polish/polish-the-readme.patch"
+}
+
 testmarktest_provide run_prelude replay_session run_in_sandbox
 testmarktest_rule 'fresh/*/session' exercise_fresh
 testmarktest_rule 'paired/*/session' exercise_paired
+testmarktest_rule 'snapshot/session' exercise_snapshot
 testmarktest_run ../docs/userguide/USAGE.md