From 2ac01ca24f78afacdf41d441d62acea3843e3395 Mon Sep 17 00:00:00 2001 From: Mark Raynsford Date: Fri, 3 May 2024 19:21:04 +0000 Subject: [PATCH] Ensure releases are serialized in order Fix: https://github.com/io7m-com/changelog/issues/25 --- README-CHANGES.xml | 9 +- .../java/com/io7m/changelog/cmdline/Main.java | 8 +- .../cmdline/internal/CLCommandChangeAdd.java | 6 +- .../internal/CLCommandReleaseBegin.java | 6 +- .../internal/CLCommandReleaseFinish.java | 6 +- .../internal/CLCommandReleaseSetVersion.java | 10 +- .../changelog/core/CChangelogFilters.java | 21 +- .../io7m/changelog/core/CChangelogType.java | 8 +- .../changelog/tests/core/CChangelogTest.java | 11 +- .../tests/xml/CRoundTripContract.java | 7 + .../tests/xml/audiobook-20240503.xml | 349 ++++++++++++++++++ .../changelog/xml/CXMLChangelogParsers.java | 7 +- 12 files changed, 421 insertions(+), 27 deletions(-) create mode 100644 com.io7m.changelog.tests/src/main/resources/com/io7m/changelog/tests/xml/audiobook-20240503.xml diff --git a/README-CHANGES.xml b/README-CHANGES.xml index 570e786..ea46efb 100644 --- a/README-CHANGES.xml +++ b/README-CHANGES.xml @@ -34,14 +34,19 @@ - + - + + + + + + diff --git a/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/Main.java b/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/Main.java index f60d55f..7ac2e3f 100644 --- a/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/Main.java +++ b/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/Main.java @@ -17,14 +17,14 @@ package com.io7m.changelog.cmdline; import com.io7m.changelog.cmdline.internal.CLCommandChangeAdd; -import com.io7m.changelog.cmdline.internal.CLCommandReleaseCurrent; -import com.io7m.changelog.cmdline.internal.CLCommandReleaseSetVersion; -import com.io7m.changelog.cmdline.internal.CLCommandWriteAtom; import com.io7m.changelog.cmdline.internal.CLCommandInitialize; -import com.io7m.changelog.cmdline.internal.CLCommandWritePlain; import com.io7m.changelog.cmdline.internal.CLCommandReleaseBegin; +import com.io7m.changelog.cmdline.internal.CLCommandReleaseCurrent; import com.io7m.changelog.cmdline.internal.CLCommandReleaseFinish; +import com.io7m.changelog.cmdline.internal.CLCommandReleaseSetVersion; import com.io7m.changelog.cmdline.internal.CLCommandVersion; +import com.io7m.changelog.cmdline.internal.CLCommandWriteAtom; +import com.io7m.changelog.cmdline.internal.CLCommandWritePlain; import com.io7m.changelog.cmdline.internal.CLCommandWriteXHTML; import com.io7m.claypot.core.CLPApplicationConfiguration; import com.io7m.claypot.core.CLPCommandConstructorType; diff --git a/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandChangeAdd.java b/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandChangeAdd.java index bf30678..bb6c80d 100644 --- a/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandChangeAdd.java +++ b/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandChangeAdd.java @@ -38,6 +38,7 @@ import java.util.List; import java.util.Optional; import java.util.ServiceLoader; +import java.util.TreeMap; /** * The "change-add" command. @@ -164,10 +165,13 @@ public Status executeActual() .setDate(now) .build(); + final var releasesNow = new TreeMap<>(changelog.releases()); + releasesNow.put(releaseWrite.version(), releaseWrite); + final var changelogWrite = CChangelog.builder() .from(changelog) - .putReleases(releaseWrite.version(), releaseWrite) + .setReleases(releasesNow) .build(); final var pathTemp = Paths.get(this.path + ".tmp"); diff --git a/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandReleaseBegin.java b/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandReleaseBegin.java index 4b7bfd3..236e823 100644 --- a/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandReleaseBegin.java +++ b/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandReleaseBegin.java @@ -35,6 +35,7 @@ import java.time.ZonedDateTime; import java.util.Optional; import java.util.ServiceLoader; +import java.util.TreeMap; import static com.io7m.claypot.core.CLPCommandType.Status.FAILURE; import static com.io7m.claypot.core.CLPCommandType.Status.SUCCESS; @@ -152,10 +153,13 @@ public Status executeActual() .setVersion(nextVersion) .build(); + final var releasesNow = new TreeMap<>(changelog.releases()); + releasesNow.put(release.version(), release); + final var newChangelog = CChangelog.builder() .from(changelog) - .putReleases(release.version(), release) + .setReleases(releasesNow) .build(); writers.write(this.path, pathTemp, newChangelog); diff --git a/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandReleaseFinish.java b/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandReleaseFinish.java index d906b9a..059f3e2 100644 --- a/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandReleaseFinish.java +++ b/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandReleaseFinish.java @@ -36,6 +36,7 @@ import java.time.ZonedDateTime; import java.util.Optional; import java.util.ServiceLoader; +import java.util.TreeMap; /** * The "release-finish" command. @@ -126,10 +127,13 @@ public Status executeActual() .setDate(ZonedDateTime.now(Clock.systemUTC())) .build(); + final var releasesNow = new TreeMap<>(changelog.releases()); + releasesNow.put(closedRelease.version(), closedRelease); + final var newChangelog = CChangelog.builder() .from(changelog) - .putReleases(closedRelease.version(), closedRelease) + .setReleases(releasesNow) .build(); writers.write(this.path, pathTemp, newChangelog); diff --git a/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandReleaseSetVersion.java b/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandReleaseSetVersion.java index f631062..b2674f1 100644 --- a/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandReleaseSetVersion.java +++ b/com.io7m.changelog.cmdline/src/main/java/com/io7m/changelog/cmdline/internal/CLCommandReleaseSetVersion.java @@ -32,8 +32,8 @@ import java.nio.file.Paths; import java.time.Clock; import java.time.ZonedDateTime; -import java.util.HashMap; import java.util.ServiceLoader; +import java.util.TreeMap; /** * The "release-set-version" command. @@ -121,14 +121,14 @@ public Status executeActual() .setVersion(version) .build(); - final var oldReleases = new HashMap<>(changelog.releases()); - oldReleases.remove(currentRelease.version()); - oldReleases.put(version, updatedRelease); + final var releasesNow = new TreeMap<>(changelog.releases()); + releasesNow.remove(currentRelease.version()); + releasesNow.put(version, updatedRelease); final var newChangelog = CChangelog.builder() .from(changelog) - .setReleases(oldReleases) + .setReleases(releasesNow) .build(); writers.write(this.path, pathTemp, newChangelog); diff --git a/com.io7m.changelog.core/src/main/java/com/io7m/changelog/core/CChangelogFilters.java b/com.io7m.changelog.core/src/main/java/com/io7m/changelog/core/CChangelogFilters.java index b92dcc2..34937d3 100644 --- a/com.io7m.changelog.core/src/main/java/com/io7m/changelog/core/CChangelogFilters.java +++ b/com.io7m.changelog.core/src/main/java/com/io7m/changelog/core/CChangelogFilters.java @@ -19,10 +19,9 @@ import com.io7m.junreachable.UnreachableCodeException; import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.TreeMap; import java.util.stream.Collectors; /** @@ -64,10 +63,10 @@ public static Optional upToAndIncluding( .stream() .filter(v -> v.compareTo(version) >= 0) .limit(count) - .collect(Collectors.toList()); + .toList(); final var releasesFiltered = - new HashMap(versions.size()); + new TreeMap(); for (final var currentVersion : versions) { releasesFiltered.put(currentVersion, releases.get(version)); } @@ -104,11 +103,15 @@ public static CChangelog limit( .collect(Collectors.toSet()); final var newReleases = - changelog.releases() - .entrySet() - .stream() - .filter(e -> versions.contains(e.getKey())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + new TreeMap(); + + changelog.releases() + .entrySet() + .stream() + .filter(e -> versions.contains(e.getKey())) + .forEach(entry -> { + newReleases.put(entry.getKey(), entry.getValue()); + }); return CChangelog.builder() .from(changelog) diff --git a/com.io7m.changelog.core/src/main/java/com/io7m/changelog/core/CChangelogType.java b/com.io7m.changelog.core/src/main/java/com/io7m/changelog/core/CChangelogType.java index 4c9c256..af09d48 100644 --- a/com.io7m.changelog.core/src/main/java/com/io7m/changelog/core/CChangelogType.java +++ b/com.io7m.changelog.core/src/main/java/com/io7m/changelog/core/CChangelogType.java @@ -25,6 +25,8 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.SortedMap; +import java.util.TreeMap; import java.util.stream.Collectors; import static org.immutables.value.Value.Immutable; @@ -47,7 +49,11 @@ public interface CChangelogType * @return The list of releases */ - Map releases(); + @Value.Default + default SortedMap releases() + { + return new TreeMap<>(); + } /** * @return The ticket systems diff --git a/com.io7m.changelog.tests/src/main/java/com/io7m/changelog/tests/core/CChangelogTest.java b/com.io7m.changelog.tests/src/main/java/com/io7m/changelog/tests/core/CChangelogTest.java index c21cc84..2f800b2 100644 --- a/com.io7m.changelog.tests/src/main/java/com/io7m/changelog/tests/core/CChangelogTest.java +++ b/com.io7m.changelog.tests/src/main/java/com/io7m/changelog/tests/core/CChangelogTest.java @@ -29,6 +29,7 @@ import java.time.Clock; import java.time.ZonedDateTime; import java.util.Optional; +import java.util.TreeMap; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -80,10 +81,13 @@ public void testNextVersionSemantic() .setUri(URI.create("http://www.example.com")) .build(); + final var releasesNow = new TreeMap(); + releasesNow.put(version, release); + final var c = CChangelog.builder() .setProject(CProjectName.of("changelog")) - .putReleases(version, release) + .setReleases(releasesNow) .putTicketSystems("x", ticketSystem) .build(); @@ -124,10 +128,13 @@ public void testFindTicketSystemDefault() .setUri(URI.create("http://www.example.com")) .build(); + final var releasesNow = new TreeMap(); + releasesNow.put(version, release); + final var c = CChangelog.builder() .setProject(CProjectName.of("changelog")) - .putReleases(version, release) + .setReleases(releasesNow) .putTicketSystems("x", ticketSystem0) .putTicketSystems("y", ticketSystem1) .build(); diff --git a/com.io7m.changelog.tests/src/main/java/com/io7m/changelog/tests/xml/CRoundTripContract.java b/com.io7m.changelog.tests/src/main/java/com/io7m/changelog/tests/xml/CRoundTripContract.java index 75c9ad1..342e4d3 100644 --- a/com.io7m.changelog.tests/src/main/java/com/io7m/changelog/tests/xml/CRoundTripContract.java +++ b/com.io7m.changelog.tests/src/main/java/com/io7m/changelog/tests/xml/CRoundTripContract.java @@ -64,6 +64,13 @@ public final void testRoundTrip2() this.runRoundTrip("/com/io7m/changelog/tests/xml/audiobook.xml"); } + @Test + public final void testRoundTrip3() + throws Exception + { + this.runRoundTrip("/com/io7m/changelog/tests/xml/audiobook-20240503.xml"); + } + private void runRoundTrip( final String name) throws IOException, URISyntaxException diff --git a/com.io7m.changelog.tests/src/main/resources/com/io7m/changelog/tests/xml/audiobook-20240503.xml b/com.io7m.changelog.tests/src/main/resources/com/io7m/changelog/tests/xml/audiobook-20240503.xml new file mode 100644 index 0000000..d31a7f0 --- /dev/null +++ b/com.io7m.changelog.tests/src/main/resources/com/io7m/changelog/tests/xml/audiobook-20240503.xml @@ -0,0 +1,349 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/com.io7m.changelog.xml.vanilla/src/main/java/com/io7m/changelog/xml/CXMLChangelogParsers.java b/com.io7m.changelog.xml.vanilla/src/main/java/com/io7m/changelog/xml/CXMLChangelogParsers.java index 34cd7aa..44c1385 100644 --- a/com.io7m.changelog.xml.vanilla/src/main/java/com/io7m/changelog/xml/CXMLChangelogParsers.java +++ b/com.io7m.changelog.xml.vanilla/src/main/java/com/io7m/changelog/xml/CXMLChangelogParsers.java @@ -23,6 +23,7 @@ import com.io7m.changelog.core.CRelease; import com.io7m.changelog.core.CTicketID; import com.io7m.changelog.core.CTicketSystem; +import com.io7m.changelog.core.CVersion; import com.io7m.changelog.core.CVersions; import com.io7m.changelog.parser.api.CParseError; import com.io7m.changelog.parser.api.CParseErrorType; @@ -58,6 +59,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.TreeMap; import java.util.function.Consumer; /** @@ -133,6 +135,7 @@ private static final class Parser private final CChange.Builder change_builder; private final CTicketSystem.Builder ticket_system_builder; private final Consumer receiver; + private final TreeMap releases; private Locator locator; private boolean failed; private int openCount; @@ -158,6 +161,7 @@ private static final class Parser this.ticket_system_builder = CTicketSystem.builder(); this.elements = new ArrayDeque<>(); this.date_format = CDateFormatters.newDateFormatter(); + this.releases = new TreeMap<>(); } @Override @@ -549,7 +553,7 @@ private void onEndChange() private void onEndRelease() { final CRelease r = this.release_builder.build(); - this.changelog_builder.putReleases(r.version(), r); + this.releases.put(r.version(), r); } @Override @@ -661,6 +665,7 @@ public CChangelog parse() throw new IOException( this.uri + " - At least one error was encountered during parsing and/or validation"); } + this.changelog_builder.setReleases(this.releases); return this.changelog_builder.build(); } catch (final SAXException e) { throw new IOException(e);