From 3668ef3967fa27b86cd8d8a456dacb6460b03089 Mon Sep 17 00:00:00 2001 From: pomali Date: Tue, 1 Aug 2023 05:18:03 -0700 Subject: [PATCH] AG-132 use semantic version in updater (#228) * use semantic version in updater * extract and add tests * refactor to createFromVersionString * private getVersionNumbers * refactor Main.getVersion to return Version * fix dev, refactor main * remove Version.createCurrent() * fix missing semicolon --- .../java/digital/slovensko/autogram/Main.java | 9 +- .../slovensko/autogram/core/Updater.java | 18 +-- .../autogram/server/InfoEndpoint.java | 2 +- .../slovensko/autogram/ui/cli/CliUI.java | 2 +- .../ui/gui/AboutDialogController.java | 2 +- .../slovensko/autogram/util/Version.java | 82 +++++++++++++ .../slovensko/autogram/util/VersionTests.java | 116 ++++++++++++++++++ 7 files changed, 217 insertions(+), 14 deletions(-) create mode 100644 src/main/java/digital/slovensko/autogram/util/Version.java create mode 100644 src/test/java/digital/slovensko/autogram/util/VersionTests.java diff --git a/src/main/java/digital/slovensko/autogram/Main.java b/src/main/java/digital/slovensko/autogram/Main.java index 6c6c383f..3b5b8826 100644 --- a/src/main/java/digital/slovensko/autogram/Main.java +++ b/src/main/java/digital/slovensko/autogram/Main.java @@ -1,6 +1,7 @@ package digital.slovensko.autogram; import digital.slovensko.autogram.core.AppStarter; +import digital.slovensko.autogram.util.Version; import static java.util.Objects.requireNonNullElse; @@ -9,7 +10,11 @@ public static void main(String[] args) { AppStarter.start(args); } - public static String getVersion() { - return requireNonNullElse(System.getProperty("jpackage.app-version"), "dev"); + public static Version getVersion() { + return Version.createFromVersionString(requireNonNullElse(System.getProperty("jpackage.app-version"), "dev")); + } + + public static String getVersionString() { + return getVersion().toString(); } } diff --git a/src/main/java/digital/slovensko/autogram/core/Updater.java b/src/main/java/digital/slovensko/autogram/core/Updater.java index d7de0ba6..4dd0ae5e 100644 --- a/src/main/java/digital/slovensko/autogram/core/Updater.java +++ b/src/main/java/digital/slovensko/autogram/core/Updater.java @@ -1,6 +1,7 @@ package digital.slovensko.autogram.core; import digital.slovensko.autogram.Main; +import digital.slovensko.autogram.util.Version; import java.io.IOException; import java.net.*; @@ -8,6 +9,7 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; + import java.util.NoSuchElementException; import com.google.gson.Gson; @@ -18,14 +20,14 @@ public class Updater { public static final String LATEST_RELEASE_API_URL = "https://api.github.com/repos/slovensko-digital/autogram/releases/latest"; public static boolean newVersionAvailable() { - if (Main.getVersion().equals("dev")) { + Version vCurrent = Main.getVersion(); + if (vCurrent.isDev()) { return false; } String latestVersionTag = ""; try { - var request = HttpRequest.newBuilder().uri(new URI(LATEST_RELEASE_API_URL)) - .header("Accept", "application/vnd.github.v3+json").GET().build(); + var request = HttpRequest.newBuilder().uri(new URI(LATEST_RELEASE_API_URL)).header("Accept", "application/vnd.github.v3+json").GET().build(); var client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build(); var response = client.send(request, HttpResponse.BodyHandlers.ofString()); @@ -33,15 +35,13 @@ public static boolean newVersionAvailable() { var json = gson.fromJson(response.body(), JsonObject.class); latestVersionTag = json.get("tag_name").getAsString(); - } catch (IOException | InterruptedException | URISyntaxException | NoSuchElementException ignored) { + } catch (IOException | InterruptedException | URISyntaxException | + NoSuchElementException ignored) { ignored.printStackTrace(); // TODO handle error return false; } - if (latestVersionTag.equals("")) - return false; - - var latestVersion = latestVersionTag.replaceAll("^v", ""); - return !Main.getVersion().equals(latestVersion); + Version vLatest = Version.createFromVersionString(latestVersionTag); + return vCurrent.compareTo(vLatest) < 0; } } diff --git a/src/main/java/digital/slovensko/autogram/server/InfoEndpoint.java b/src/main/java/digital/slovensko/autogram/server/InfoEndpoint.java index 269e10a7..113fc075 100644 --- a/src/main/java/digital/slovensko/autogram/server/InfoEndpoint.java +++ b/src/main/java/digital/slovensko/autogram/server/InfoEndpoint.java @@ -13,7 +13,7 @@ public class InfoEndpoint implements HttpHandler { @Override public void handle(HttpExchange exchange) throws IOException { - var response = new InfoResponse(Main.getVersion(), getStatus()); + var response = new InfoResponse(Main.getVersionString(), getStatus()); var gson = new Gson(); try { diff --git a/src/main/java/digital/slovensko/autogram/ui/cli/CliUI.java b/src/main/java/digital/slovensko/autogram/ui/cli/CliUI.java index 4a153c5d..017c1062 100644 --- a/src/main/java/digital/slovensko/autogram/ui/cli/CliUI.java +++ b/src/main/java/digital/slovensko/autogram/ui/cli/CliUI.java @@ -195,7 +195,7 @@ public void onAboutInfo() { Licencia a zdrojové kódy Tento softvér pôvodne vychádza projektu z Octosign White Label od Jakuba Ďuraša, ktorý je licencovaný pod MIT licenciou. So súhlasom autora je táto verzia distribuovaná pod licenciou EUPL v1.2. Zdrojové kódy sú dostupné na https://github.com/slovensko-digital/autogram."""); - System.out.println(String.format("Verzia: %s", Main.getVersion())); + System.out.println(String.format("Verzia: %s", Main.getVersionString())); } @Override diff --git a/src/main/java/digital/slovensko/autogram/ui/gui/AboutDialogController.java b/src/main/java/digital/slovensko/autogram/ui/gui/AboutDialogController.java index 54a72833..4e38db45 100644 --- a/src/main/java/digital/slovensko/autogram/ui/gui/AboutDialogController.java +++ b/src/main/java/digital/slovensko/autogram/ui/gui/AboutDialogController.java @@ -22,7 +22,7 @@ public AboutDialogController(HostServices hostServices) { } public void initialize() { - versionText.setText(Main.getVersion()); + versionText.setText(Main.getVersionString()); } public void githubLinkAction(ActionEvent ignored) { diff --git a/src/main/java/digital/slovensko/autogram/util/Version.java b/src/main/java/digital/slovensko/autogram/util/Version.java new file mode 100644 index 00000000..a8d63f6b --- /dev/null +++ b/src/main/java/digital/slovensko/autogram/util/Version.java @@ -0,0 +1,82 @@ +package digital.slovensko.autogram.util; + +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +public class Version implements Comparable { + + private final int[] versionNumbers; + private final boolean dev; + + public Version(int[] versionNumbers) { + this.versionNumbers = versionNumbers; + this.dev = false; + } + + /** + * Dev version constructor + */ + public Version() { + this.versionNumbers = new int[]{}; + this.dev = true; + } + + public static Version createFromVersionString(String version) { + version = version.replaceAll("^v", ""); + + if (version.equals("")) { + return new Version(new int[]{}); + } + + if (version.equals("dev")) { + return new Version(); + } + + var versionNumbers = Stream.of(version.split("\\.")).mapToInt(Integer::parseInt).toArray(); + return new Version(versionNumbers); + } + + + public String toString() { + if (dev) { + return "dev"; + } + return IntStream.of(versionNumbers).mapToObj(Integer::toString).collect(Collectors.joining(".")); + } + + + public boolean isDev() { + return dev; + } + + @Override + public int compareTo(Version o) { + if (dev && o.dev) { + return 0; + } + + if (dev) { + return 1; + } + + if (o.dev) { + return -1; + } + + var otherNumbers = o.getVersionNumbers(); + for (int i = 0; i < Math.min(versionNumbers.length, otherNumbers.length); i++) { + var diff = versionNumbers[i] - otherNumbers[i]; + if (diff != 0) { + return diff; + } + } + return versionNumbers.length - otherNumbers.length; + } + + + private int[] getVersionNumbers() { + return versionNumbers; + } + +} diff --git a/src/test/java/digital/slovensko/autogram/util/VersionTests.java b/src/test/java/digital/slovensko/autogram/util/VersionTests.java new file mode 100644 index 00000000..15436de3 --- /dev/null +++ b/src/test/java/digital/slovensko/autogram/util/VersionTests.java @@ -0,0 +1,116 @@ +package digital.slovensko.autogram.util; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +public class VersionTests { + + @Test + public void testVersionCompareTo() { + var v1 = Version.createFromVersionString("1.0.0"); + var v2 = Version.createFromVersionString("1.0.1"); + var v3 = Version.createFromVersionString("v1.1.0"); + var v4 = Version.createFromVersionString("v2.0.0"); + var v5 = Version.createFromVersionString("2.0.1"); + var v6 = Version.createFromVersionString("2.1.0"); + var v7 = Version.createFromVersionString("2.1.1"); + + assertTrue(v1.compareTo(v1) == 0); + assertTrue(v1.compareTo(v2) < 0); + assertTrue(v1.compareTo(v3) < 0); + assertTrue(v1.compareTo(v4) < 0); + assertTrue(v1.compareTo(v5) < 0); + assertTrue(v1.compareTo(v6) < 0); + assertTrue(v1.compareTo(v7) < 0); + + assertTrue(v2.compareTo(v1) > 0); + assertTrue(v2.compareTo(v2) == 0); + assertTrue(v2.compareTo(v3) < 0); + assertTrue(v2.compareTo(v4) < 0); + assertTrue(v2.compareTo(v5) < 0); + assertTrue(v2.compareTo(v6) < 0); + assertTrue(v2.compareTo(v7) < 0); + + assertTrue(v3.compareTo(v1) > 0); + assertTrue(v3.compareTo(v2) > 0); + assertTrue(v3.compareTo(v3) == 0); + assertTrue(v3.compareTo(v4) < 0); + assertTrue(v3.compareTo(v5) < 0); + assertTrue(v3.compareTo(v6) < 0); + assertTrue(v3.compareTo(v7) < 0); + + assertTrue(v4.compareTo(v1) > 0); + assertTrue(v4.compareTo(v2) > 0); + assertTrue(v4.compareTo(v3) > 0); + assertTrue(v4.compareTo(v4) == 0); + assertTrue(v4.compareTo(v5) < 0); + assertTrue(v4.compareTo(v6) < 0); + assertTrue(v4.compareTo(v7) < 0); + + assertTrue(v5.compareTo(v1) > 0); + assertTrue(v5.compareTo(v2) > 0); + assertTrue(v5.compareTo(v3) > 0); + assertTrue(v5.compareTo(v4) > 0); + assertTrue(v5.compareTo(v5) == 0); + assertTrue(v5.compareTo(v6) < 0); + assertTrue(v5.compareTo(v7) < 0); + + assertTrue(v6.compareTo(v1) > 0); + assertTrue(v6.compareTo(v2) > 0); + assertTrue(v6.compareTo(v3) > 0); + assertTrue(v6.compareTo(v4) > 0); + assertTrue(v6.compareTo(v5) > 0); + assertTrue(v6.compareTo(v6) == 0); + assertTrue(v6.compareTo(v7) < 0); + + assertTrue(v7.compareTo(v1) > 0); + assertTrue(v7.compareTo(v2) > 0); + assertTrue(v7.compareTo(v3) > 0); + assertTrue(v7.compareTo(v4) > 0); + assertTrue(v7.compareTo(v5) > 0); + assertTrue(v7.compareTo(v6) > 0); + assertTrue(v7.compareTo(v7) == 0); + } + + @Test + public void testVersionCompareToWithDifferentLength() { + var v0 = Version.createFromVersionString(""); + var v1 = Version.createFromVersionString("1.0.0"); + var v2 = Version.createFromVersionString("0.2"); + var v3 = Version.createFromVersionString("1"); + + assertTrue(v0.compareTo(v0) == 0); + assertTrue(v0.compareTo(v1) < 0); + assertTrue(v0.compareTo(v2) < 0); + assertTrue(v0.compareTo(v3) < 0); + + assertTrue(v1.compareTo(v0) > 0); + assertTrue(v1.compareTo(v1) == 0); + assertTrue(v1.compareTo(v2) > 0); + assertTrue(v1.compareTo(v3) > 0); + + assertTrue(v2.compareTo(v0) > 0); + assertTrue(v2.compareTo(v1) < 0); + assertTrue(v2.compareTo(v2) == 0); + assertTrue(v2.compareTo(v3) < 0); + + assertTrue(v3.compareTo(v0) > 0); + assertTrue(v3.compareTo(v1) < 0); + assertTrue(v3.compareTo(v2) > 0); + assertTrue(v3.compareTo(v3) == 0); + } + + @Test + public void testDev(){ + var dev = Version.createFromVersionString("dev"); + var v1 = Version.createFromVersionString("1.0.0"); + var v2 = Version.createFromVersionString("0.2"); + + assertTrue(dev.compareTo(dev) == 0); + assertTrue(dev.compareTo(v1) > 0); + assertTrue(dev.compareTo(v2) > 0); + assertTrue(v1.compareTo(dev) < 0); + assertTrue(v2.compareTo(dev) < 0); + } +} \ No newline at end of file