diff --git a/CHANGELOG.md b/CHANGELOG.md
index c495bec63..6682f247d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -127,6 +127,21 @@ follow semantic versioning; release dates are ISO 8601.
### Documentation
+- **The example catalogue is built one way, and it starts empty.** The runner only ever
+ wrote, so a renamed or deleted example left its old document behind — published to the
+ site, counted by the guards that read the tree, and indistinguishable from a current
+ one. Generation now clears the output tree first, inside the runner itself, so the
+ release script, CI and the tests all get the same guarantee instead of the one path
+ that happened to remember. `ShowcaseSync` removes the directories as well as the files
+ it replaces, which makes the published tree a function of the catalogue rather than a
+ record of everything ever generated.
+- **Nine committed previews are gone and two examples now run.** Seven were pre-2.0
+ renders of CV presets whose current versions the runner already produced, so the
+ gallery linked the older snapshot of each; those links follow the current render and
+ the stale files are removed. Two more, an invoice and a proposal, were left by a rename
+ and nothing linked them at all. The cover-letter example and a custom-theme CV were
+ never wired into the runner, so one of them backed a link with a file no code produced
+ — both are generated now, and both have a showcase entry.
- **The template-authoring guide describes the packages that exist.** It told a
contributor to put a new family under `templates..v2` in exactly five
sub-packages, one of them a per-family `theme/` — a layout 2.0 replaced. A family has
diff --git a/assets/readme/examples/cover-letter.pdf b/assets/readme/examples/cover-letter.pdf
index 3cf941676..bd5ed48a8 100644
Binary files a/assets/readme/examples/cover-letter.pdf and b/assets/readme/examples/cover-letter.pdf differ
diff --git a/assets/readme/examples/cv-classic-serif.pdf b/assets/readme/examples/cv-classic-serif-v2.pdf
similarity index 87%
rename from assets/readme/examples/cv-classic-serif.pdf
rename to assets/readme/examples/cv-classic-serif-v2.pdf
index c0ec3d9ff..67919255f 100644
Binary files a/assets/readme/examples/cv-classic-serif.pdf and b/assets/readme/examples/cv-classic-serif-v2.pdf differ
diff --git a/assets/readme/examples/cv-compact-mono.pdf b/assets/readme/examples/cv-compact-mono-v2.pdf
similarity index 82%
rename from assets/readme/examples/cv-compact-mono.pdf
rename to assets/readme/examples/cv-compact-mono-v2.pdf
index 1ecfdc021..a862ba987 100644
Binary files a/assets/readme/examples/cv-compact-mono.pdf and b/assets/readme/examples/cv-compact-mono-v2.pdf differ
diff --git a/assets/readme/examples/cv-engineering-resume.pdf b/assets/readme/examples/cv-engineering-resume-v2.pdf
similarity index 80%
rename from assets/readme/examples/cv-engineering-resume.pdf
rename to assets/readme/examples/cv-engineering-resume-v2.pdf
index 1b2312a6d..1c14c11e8 100644
Binary files a/assets/readme/examples/cv-engineering-resume.pdf and b/assets/readme/examples/cv-engineering-resume-v2.pdf differ
diff --git a/assets/readme/examples/cv-modern-professional-v2.pdf b/assets/readme/examples/cv-modern-professional-v2.pdf
new file mode 100644
index 000000000..0b9c4562f
Binary files /dev/null and b/assets/readme/examples/cv-modern-professional-v2.pdf differ
diff --git a/assets/readme/examples/cv-modern-professional.pdf b/assets/readme/examples/cv-modern-professional.pdf
deleted file mode 100644
index f75d5989e..000000000
Binary files a/assets/readme/examples/cv-modern-professional.pdf and /dev/null differ
diff --git a/assets/readme/examples/cv-nordic-clean.pdf b/assets/readme/examples/cv-nordic-clean-v2.pdf
similarity index 83%
rename from assets/readme/examples/cv-nordic-clean.pdf
rename to assets/readme/examples/cv-nordic-clean-v2.pdf
index c99d95033..80a6094d0 100644
Binary files a/assets/readme/examples/cv-nordic-clean.pdf and b/assets/readme/examples/cv-nordic-clean-v2.pdf differ
diff --git a/assets/readme/examples/cv-panel.pdf b/assets/readme/examples/cv-panel-v2.pdf
similarity index 80%
rename from assets/readme/examples/cv-panel.pdf
rename to assets/readme/examples/cv-panel-v2.pdf
index 97dea47d0..ce10bbe5f 100644
Binary files a/assets/readme/examples/cv-panel.pdf and b/assets/readme/examples/cv-panel-v2.pdf differ
diff --git a/assets/readme/examples/cv-timeline-minimal.pdf b/assets/readme/examples/cv-timeline-minimal-v2.pdf
similarity index 94%
rename from assets/readme/examples/cv-timeline-minimal.pdf
rename to assets/readme/examples/cv-timeline-minimal-v2.pdf
index 6443f0e50..cc2b9dc94 100644
Binary files a/assets/readme/examples/cv-timeline-minimal.pdf and b/assets/readme/examples/cv-timeline-minimal-v2.pdf differ
diff --git a/assets/readme/examples/invoice.pdf b/assets/readme/examples/invoice.pdf
deleted file mode 100644
index cb52dbbab..000000000
Binary files a/assets/readme/examples/invoice.pdf and /dev/null differ
diff --git a/assets/readme/examples/proposal.pdf b/assets/readme/examples/proposal.pdf
deleted file mode 100644
index 6081db2c9..000000000
Binary files a/assets/readme/examples/proposal.pdf and /dev/null differ
diff --git a/examples/README.md b/examples/README.md
index 128c01f12..94d3dde57 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -56,7 +56,7 @@ are with the canonical DSL, then jump to its detailed section below.
| Example | What it shows | Preview · Source |
|---|---|---|
-| [CV — single template](#cv-single-template) | One CV via `ModernProfessional.create()` on a `CvDocument` | [PDF](../assets/readme/examples/cv-modern-professional.pdf) · [Source](src/main/java/com/demcha/examples/templates/cv/CvFileExample.java) |
+| [CV — single template](#cv-single-template) | One CV via `ModernProfessional.create()` on a `CvDocument` | [PDF](../assets/readme/examples/cv-modern-professional-v2.pdf) · [Source](src/main/java/com/demcha/examples/templates/cv/v2/CvModernV2Example.java) |
| [Invoice — cinematic V2](#invoice-cinematic-v2) | `ModernInvoice + BrandTheme.invoiceModern()` — the recommended invoice path | [PDF](../assets/readme/examples/invoice-cinematic.pdf) · [Source](src/main/java/com/demcha/examples/templates/invoice/InvoiceCinematicFileExample.java) |
| [Cover Letter](#cover-letter) | One-page cover letter composed in the canonical DSL, section presets carrying the hierarchy | [PDF](../assets/readme/examples/cover-letter.pdf) · [Source](src/main/java/com/demcha/examples/templates/coverletter/CoverLetterFileExample.java) |
| [Module-first Profile](#module-first-profile) | Authoring directly against `DocumentSession.module(...).paragraph(...)` — DSL-direct, no template | [PDF](../assets/readme/examples/module-first-profile.pdf) · [Source](src/main/java/com/demcha/examples/flagships/ModuleFirstFileExample.java) |
@@ -205,8 +205,8 @@ One CV rendered through the layered template surface:
The preset is one final class with `create()` / `create(BrandTheme)`
factories — copy-and-tweak rather than fork-a-monolith.
-[📄 View PDF](../assets/readme/examples/cv-modern-professional.pdf) ·
-[📜 Full source](src/main/java/com/demcha/examples/templates/cv/CvFileExample.java)
+[📄 View PDF](../assets/readme/examples/cv-modern-professional-v2.pdf) ·
+[📜 Full source](src/main/java/com/demcha/examples/templates/cv/v2/CvModernV2Example.java)
### CV — template gallery
@@ -218,15 +218,19 @@ preset for your own CV product. Each preset is a one-liner factory
| Variant | PDF |
|---|---|
-| Modern professional | [PDF](../assets/readme/examples/cv-modern-professional.pdf) |
-| Nordic clean | [PDF](../assets/readme/examples/cv-nordic-clean.pdf) |
-| Classic serif | [PDF](../assets/readme/examples/cv-classic-serif.pdf) |
-| Compact mono | [PDF](../assets/readme/examples/cv-compact-mono.pdf) |
-| Timeline minimal | [PDF](../assets/readme/examples/cv-timeline-minimal.pdf) |
-| Engineering resume | [PDF](../assets/readme/examples/cv-engineering-resume.pdf) |
-| Panel | [PDF](../assets/readme/examples/cv-panel.pdf) |
+| Modern professional | [PDF](../assets/readme/examples/cv-modern-professional-v2.pdf) |
+| Nordic clean | [PDF](../assets/readme/examples/cv-nordic-clean-v2.pdf) |
+| Classic serif | [PDF](../assets/readme/examples/cv-classic-serif-v2.pdf) |
+| Compact mono | [PDF](../assets/readme/examples/cv-compact-mono-v2.pdf) |
+| Timeline minimal | [PDF](../assets/readme/examples/cv-timeline-minimal-v2.pdf) |
+| Engineering resume | [PDF](../assets/readme/examples/cv-engineering-resume-v2.pdf) |
+| Panel | [PDF](../assets/readme/examples/cv-panel-v2.pdf) |
| Executive · BoxedSections · CenteredHeadline · BlueBanner · EditorialBlue · SidebarPortrait · MonogramSidebar · MintEditorial · MinimalUnderlined | run the gallery to render |
+The previews above come from the per-preset examples under
+[`templates/cv/v2/`](src/main/java/com/demcha/examples/templates/cv/v2), which the
+catalogue runner generates. The gallery below renders every preset from one entry point
+instead, and is not part of that run — use it to produce the whole set locally:
[📜 Full source](src/main/java/com/demcha/examples/templates/cv/CvTemplateGalleryFileExample.java)
### Cover letter — template gallery
diff --git a/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java b/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java
index b31065cb1..d2276cc3c 100644
--- a/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java
+++ b/examples/src/main/java/com/demcha/examples/GenerateAllExamples.java
@@ -43,6 +43,7 @@
import com.demcha.examples.features.title.BookTemplateExample;
import com.demcha.examples.features.title.PoetryTitlePageExample;
import com.demcha.examples.features.transforms.TransformsExample;
+import com.demcha.examples.support.ExampleOutputPaths;
import com.demcha.examples.flagships.BusinessReportExample;
import com.demcha.examples.flagships.BusinessReportPptxExample;
import com.demcha.examples.flagships.EngineDeckExample;
@@ -58,6 +59,7 @@
import com.demcha.examples.flagships.MavenBannerPptxExample;
import com.demcha.examples.flagships.ModuleFirstFileExample;
import com.demcha.examples.flagships.TwinOutputExample;
+import com.demcha.examples.templates.coverletter.CoverLetterFileExample;
import com.demcha.examples.templates.coverletter.CvBlueBannerLetterV2Example;
import com.demcha.examples.templates.coverletter.CvBoxedSectionsLetterV2Example;
import com.demcha.examples.templates.coverletter.CvCenteredHeadlineLetterV2Example;
@@ -82,6 +84,7 @@
import com.demcha.examples.templates.cv.v2.CvEngineeringResumeExample;
import com.demcha.examples.templates.cv.v2.CvExecutiveExample;
import com.demcha.examples.templates.cv.v2.CvMinimalUnderlinedExample;
+import com.demcha.examples.templates.cv.v2.CvMintEditorialCustomExample;
import com.demcha.examples.templates.cv.v2.CvMintEditorialExample;
import com.demcha.examples.templates.cv.v2.CvModernV2Example;
import com.demcha.examples.templates.cv.v2.CvMonogramSidebarExample;
@@ -109,6 +112,11 @@ private GenerateAllExamples() {
}
public static void main(String[] args) throws Exception {
+ // The catalogue is a statement about the code, so it starts empty: an
+ // example renamed or deleted must not leave its old document behind for
+ // the showcase to publish and the guards to count.
+ ExampleOutputPaths.clean();
+
// === Templates ===
// CV / Resume (v2 layered — 16 presets, one example per preset)
System.out.println("Generated: " + CvBlueBannerExample.generate());
@@ -121,6 +129,8 @@ public static void main(String[] args) throws Exception {
System.out.println("Generated: " + CvExecutiveExample.generate());
System.out.println("Generated: " + CvMinimalUnderlinedExample.generate());
System.out.println("Generated: " + CvMintEditorialExample.generate());
+ System.out.println("Generated: " + CvMintEditorialCustomExample.generate());
+ System.out.println("Generated: " + CoverLetterFileExample.generate());
System.out.println("Generated: " + CvModernV2Example.generate());
System.out.println("Generated: " + CvMonogramSidebarExample.generate());
System.out.println("Generated: " + CvNordicCleanExample.generate());
diff --git a/examples/src/main/java/com/demcha/examples/support/ExampleOutputPaths.java b/examples/src/main/java/com/demcha/examples/support/ExampleOutputPaths.java
index 4153e721f..2d022c559 100644
--- a/examples/src/main/java/com/demcha/examples/support/ExampleOutputPaths.java
+++ b/examples/src/main/java/com/demcha/examples/support/ExampleOutputPaths.java
@@ -1,15 +1,70 @@
package com.demcha.examples.support;
+import java.io.IOException;
+import java.nio.file.AccessDeniedException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Comparator;
+import java.util.stream.Stream;
public final class ExampleOutputPaths {
private ExampleOutputPaths() {
}
+ /** The tree every example writes into. */
+ public static Path root() {
+ return baseDirectory().resolve("target").resolve("generated-pdfs")
+ .toAbsolutePath().normalize();
+ }
+
+ /**
+ * Empties the output tree so what remains is exactly what this run produced.
+ *
+ * The examples only write. Rename an example's output or delete the example and
+ * its old file stays behind, indistinguishable from a current one — the showcase
+ * then publishes a document nothing produces, and the guards that read the tree
+ * count it as evidence. Clearing first is what makes the tree a statement about the
+ * code rather than about the order in which commands were run.
+ *
+ * @return the emptied root
+ */
+ public static Path clean() throws IOException {
+ Path root = root();
+ if (Files.isDirectory(root)) {
+ try (Stream paths = Files.walk(root)) {
+ for (Path path : paths.sorted(Comparator.reverseOrder()).toList()) {
+ if (!path.equals(root)) {
+ delete(path);
+ }
+ }
+ }
+ }
+ Files.createDirectories(root);
+ return root;
+ }
+
+ /**
+ * Deletes one entry, translating the failure a reader can actually act on.
+ *
+ * A document held open in a viewer is the way this fails on Windows, and it is
+ * common enough that the runbook lists it. The raw {@code AccessDeniedException}
+ * arrives with a path and nothing else, at the very start of a run that has produced
+ * nothing yet, which reads like the generator is broken rather than like a window
+ * needs closing.
+ */
+ private static void delete(Path path) throws IOException {
+ try {
+ Files.delete(path);
+ } catch (AccessDeniedException blocked) {
+ throw new IOException("Cannot clear " + path + " before regenerating the examples."
+ + " Something is holding the file open — a PDF viewer is the usual answer on"
+ + " Windows. Close it and run again.", blocked);
+ }
+ }
+
public static Path prepare(String fileName) throws Exception {
- Path root = baseDirectory().resolve("target").resolve("generated-pdfs");
+ Path root = root();
Files.createDirectories(root);
return root.resolve(fileName).toAbsolutePath().normalize();
}
@@ -26,7 +81,7 @@ public static Path prepare(String fileName) throws Exception {
* @return absolute path under the categorised generated-pdfs tree
*/
public static Path prepare(String category, String fileName) throws Exception {
- Path root = baseDirectory().resolve("target").resolve("generated-pdfs").resolve(category);
+ Path root = root().resolve(category);
Files.createDirectories(root);
return root.resolve(fileName).toAbsolutePath().normalize();
}
diff --git a/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java b/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java
index f67a35441..452312841 100644
--- a/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java
+++ b/examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java
@@ -59,8 +59,16 @@ record Entry(String title, String description, List tags, String codeUrl
cv("cv-monogram-sidebar-v2", "CvMonogramSidebarExample", "Monogram Sidebar", "Sidebar with monogram badge, accent rule, and structured contact + skills column.", "sidebar", "monogram");
cv("cv-minimal-underlined-v2", "CvMinimalUnderlinedExample", "Minimal Underlined", "Single-column layout with underlined section titles and tight whitespace — minimalist reference shape.", "minimal");
cv("cv-mint-editorial-v2", "CvMintEditorialExample", "Mint Editorial", "Magazine-style editorial CV with mint accent palette and two-column body.", "editorial", "mint");
+ cv("cv-mint-editorial-v2-custom", "CvMintEditorialCustomExample", "Mint Editorial (custom band)", "The same preset with one colour changed through its Options — a kraft-paper masthead band, everything else left at the preset's defaults.", "editorial", "mint");
// ===== Templates / Cover Letter (v2 layered, paired 1:1 with CV) =====
+ // Registered directly: letter() points at the layered preset examples under
+ // coverletter/v2, and this one sits a level up because it composes without a
+ // preset at all.
+ ENTRIES.put("cover-letter", entry("Cover Letter",
+ "One page composed straight in the canonical DSL — section presets carry the hierarchy, no template involved.",
+ withCategory("letter"),
+ EX_BASE + "/templates/coverletter/CoverLetterFileExample.java"));
letter("cover-letter-modern-professional-v2", "CvModernProfessionalLetterV2Example", "Modern Professional letter", "Letter paired with the Modern Professional CV palette.");
letter("cover-letter-nordic-clean-v2", "CvNordicCleanLetterV2Example", "Nordic Clean letter", "Letter paired with the Nordic Clean CV palette.");
letter("cover-letter-classic-serif-v2", "CvClassicSerifLetterV2Example", "Classic Serif letter", "Letter with Times-style serif typography.");
diff --git a/examples/src/main/java/com/demcha/examples/support/ShowcaseSync.java b/examples/src/main/java/com/demcha/examples/support/ShowcaseSync.java
index a31ff462c..60e541103 100644
--- a/examples/src/main/java/com/demcha/examples/support/ShowcaseSync.java
+++ b/examples/src/main/java/com/demcha/examples/support/ShowcaseSync.java
@@ -16,7 +16,10 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
@@ -89,6 +92,7 @@ public static void main(String[] args) throws Exception {
+ ". Run GenerateAllExamples first — refusing to clear the published"
+ " showcase and write an empty manifest.");
}
+ requireCompleteCatalogue(pdfs, generatedPdfs);
// The copy below replaces files but never removes them, so an example that was
// renamed or deleted kept its artifact published on GitHub Pages indefinitely —
@@ -189,21 +193,74 @@ private static void renderPreview(Path pdfPath, Path pngTarget) throws IOExcepti
}
/**
- * Removes every published file under a subtree, leaving the directories in place.
- * Only files matter: git tracks no empty directory, and the copy below recreates
- * whatever it needs. Deleting the directories too is what makes this fragile on
- * Windows, where a just-closed handle can still fail the parent's removal with
- * {@code AccessDeniedException}. A missing tree is a no-op — the normal case on a
+ * Refuses to publish a catalogue that is missing documents the register describes.
+ *
+ * "Not empty" stopped being enough the moment generation began by clearing the
+ * tree. A run that dies partway now leaves exactly the documents written before the
+ * throw, and that passes an emptiness check — so the sync would mirror the remains,
+ * delete every published file the run never got to, and rewrite the manifest to
+ * match. The site ends up internally consistent and quietly missing half its
+ * examples, which is worse than an obvious failure.
+ *
+ * The register is the yardstick because it is the one list that says what the
+ * catalogue is meant to contain. Deleting an example legitimately shrinks the
+ * catalogue, and that stays possible — the entry goes with it, which the coverage
+ * guard requires anyway.
+ */
+ private static void requireCompleteCatalogue(List pdfs, Path generatedPdfs) {
+ Set produced = pdfs.stream()
+ .map(pdf -> pdf.getFileName().toString())
+ .map(name -> name.substring(0, name.length() - ".pdf".length()))
+ .collect(Collectors.toCollection(TreeSet::new));
+
+ Set missing = new TreeSet<>(ShowcaseMetadata.registeredEntries().keySet());
+ missing.removeAll(produced);
+ if (!missing.isEmpty()) {
+ throw new IllegalStateException(
+ "The generated catalogue is missing " + missing.size() + " document(s) the"
+ + " showcase register describes: " + missing + ". Generation starts by"
+ + " emptying " + generatedPdfs + ", so a run that failed partway leaves"
+ + " exactly what it managed to write. Re-run GenerateAllExamples and let it"
+ + " finish — publishing now would delete the missing documents from the site"
+ + " and rewrite the manifest without them. If an example was removed on"
+ + " purpose, remove its register entry too.");
+ }
+ }
+
+ /**
+ * Empties a published subtree. A missing tree is a no-op — the normal case on a
* fresh checkout.
+ *
+ * Every file goes, and a failure there stops the sync: a published file that
+ * survives is a document the site still serves and the manifest no longer lists.
+ *
+ * Directories are removed too, deepest first, but only where the filesystem
+ * allows. On Windows a just-closed handle can still fail the parent's removal with
+ * {@code AccessDeniedException} — observed here on
+ * {@code web/showcase/pdf/templates/schedule} — and an empty folder left behind is
+ * a cosmetic blemish on the deployed tree, invisible to git and to every reader who
+ * arrives through the manifest. Failing the whole publish over one would trade a
+ * real problem for a tidiness preference.
*/
private static void deletePublishedFiles(Path root) throws IOException {
if (!Files.exists(root)) {
return;
}
try (Stream walk = Files.walk(root)) {
- List files = walk.filter(Files::isRegularFile).toList();
- for (Path file : files) {
- Files.delete(file);
+ for (Path path : walk.sorted(Comparator.reverseOrder()).toList()) {
+ if (path.equals(root)) {
+ continue;
+ }
+ if (Files.isDirectory(path)) {
+ try {
+ Files.delete(path);
+ } catch (IOException locked) {
+ System.out.println("Left in place (the filesystem would not remove it): "
+ + path + " — " + locked.getClass().getSimpleName());
+ }
+ } else {
+ Files.delete(path);
+ }
}
}
}
diff --git a/examples/src/test/java/com/demcha/examples/GeneratedCatalogue.java b/examples/src/test/java/com/demcha/examples/GeneratedCatalogue.java
index 447715788..c56ed688b 100644
--- a/examples/src/test/java/com/demcha/examples/GeneratedCatalogue.java
+++ b/examples/src/test/java/com/demcha/examples/GeneratedCatalogue.java
@@ -1,10 +1,6 @@
package com.demcha.examples;
-import java.io.IOException;
-import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Comparator;
-import java.util.stream.Stream;
/**
* The generated example tree, produced once per JVM for whichever test asks first.
@@ -13,13 +9,11 @@
* metadata that describes them — and running the whole catalogue twice would double the
* cost of the examples job for nothing.
*
- * The tree is emptied before it is rebuilt. The runner only writes, so without that
- * an artefact from an earlier build survives: delete an example and leave its showcase
- * entry behind, run without {@code clean}, and the coverage guard matches the entry
- * against yesterday's file and passes on a document the current code no longer writes.
- * That is invisible to a negative test, because the negative test starts from a tree the
- * runner just wrote. CI happens to be safe — it compiles clean first — which only means
- * the local run is the lenient one, and the local run is where the guard is read.
+ * The emptying belongs to {@link GenerateAllExamples} rather than to this class. The
+ * release script and CI run the runner directly, so a clean step that lived only here
+ * would leave those two paths behind — and the failure it prevents, a document surviving
+ * an example that no longer writes it, is exactly the kind that shows up in what gets
+ * published rather than in what gets tested.
*
* Public because the metadata guard sits in the {@code support} package, beside the
* package-private register it reads. Test scope only — nothing here is published.
@@ -42,32 +36,13 @@ public static synchronized Path generateOnce() throws Exception {
}
/**
- * Empties the tree and runs the whole catalogue into it. The path {@link #generateOnce}
- * takes, exposed so the guard covering the emptying can drive it from a known state
- * instead of depending on which test class happened to run first.
+ * Runs the catalogue, which empties the tree before writing it. Exposed so the guard
+ * covering the emptying can drive it from a known state instead of depending on
+ * which test class happened to run first.
*/
static synchronized Path regenerate() throws Exception {
- clear(ROOT);
- Files.createDirectories(ROOT);
GenerateAllExamples.main(new String[0]);
generated = true;
return ROOT;
}
-
- /**
- * Deletes everything under {@code root}, deepest entry first so a directory is empty
- * by the time it is removed. {@code root} itself stays.
- */
- private static void clear(Path root) throws IOException {
- if (!Files.isDirectory(root)) {
- return;
- }
- try (Stream paths = Files.walk(root)) {
- for (Path path : paths.sorted(Comparator.reverseOrder()).toList()) {
- if (!path.equals(root)) {
- Files.delete(path);
- }
- }
- }
- }
}