From 3bfe32877da69c7a4d67e0c92a0660d094ccb3c1 Mon Sep 17 00:00:00 2001
From: "James R. Perkins"
Date: Fri, 22 Mar 2024 10:19:43 -0700
Subject: [PATCH 1/2] [17] Add an option to ignore the SNAPSHOT extension when
comparing versions.
Signed-off-by: James R. Perkins
---
.../plugin/tools/VersionComparator.java | 148 ++++++++++++++----
.../wildfly/plugin/tools/VersionTestCase.java | 14 +-
2 files changed, 133 insertions(+), 29 deletions(-)
diff --git a/src/main/java/org/wildfly/plugin/tools/VersionComparator.java b/src/main/java/org/wildfly/plugin/tools/VersionComparator.java
index ab060a2..8176bf8 100644
--- a/src/main/java/org/wildfly/plugin/tools/VersionComparator.java
+++ b/src/main/java/org/wildfly/plugin/tools/VersionComparator.java
@@ -6,22 +6,88 @@
package org.wildfly.plugin.tools;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
+import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
/**
- * Compares two versions.
+ * Compares two versions. The comparison is case-insensitive.
+ *
+ * Some qualifiers map to other qualifiers. Below is a table of those mappings.
+ *
+ *
+ * Qualifier |
+ * Mapping |
+ *
+ *
+ * GA |
+ * Final |
+ *
+ *
+ * a |
+ * Alpha |
+ *
+ *
+ * b |
+ * Beta |
+ *
+ *
+ * m |
+ * Milestone |
+ *
+ *
+ * cr |
+ * rc |
+ *
+ *
+ *
*
* @author James R. Perkins
*/
public class VersionComparator implements Comparator {
private static final VersionComparator INSTANCE = new VersionComparator();
+ private static final VersionComparator IGNORE_INSTANCE = new VersionComparator(true);
+
+ private final boolean ignoreSnapshots;
+
+ /**
+ * Creates a new version comparator.
+ */
+ public VersionComparator() {
+ this(false);
+ }
+
+ private VersionComparator(final boolean ignoreSnapshots) {
+ this.ignoreSnapshots = ignoreSnapshots;
+ }
+
+ /**
+ * Returns an instance of a version comparator.
+ *
+ * @return a version comparator instance
+ */
+ public static VersionComparator getInstance() {
+ return getInstance(false);
+ }
+
+ /**
+ * Returns an instance of a version comparator which optionally ignore the SNAPSHOT release extension. This can
+ * be useful for cases where you want to compare a version is at least a base version, not caring if it's a
+ * SNAPSHOT.
+ *
+ * @param ignoreSnapshots {@code true} to ignore the SNAPSHOT release extension, otherwise {@code false} which
+ * values a SNAPSHOT dependency less than a non-SNAPSHOT of the same version
+ *
+ * @return a version comparator instance
+ */
+ public static VersionComparator getInstance(final boolean ignoreSnapshots) {
+ return ignoreSnapshots ? IGNORE_INSTANCE : INSTANCE;
+ }
/**
* Compares the first version against the second version.
@@ -35,14 +101,41 @@ public class VersionComparator implements Comparator {
* @see Comparator#compare(Object, Object)
*/
public static int compareVersion(final String v1, final String v2) {
- return INSTANCE.compare(v1, v2);
+ return compareVersion(false, v1, v2);
+ }
+
+ /**
+ * Compares the first version against the second version optionally ignoring if either version has a SNAPSHOT
+ * release extension. This can be useful for cases where you want to compare a version is at least a base version,
+ * not caring if it's a SNAPSHOT.
+ *
+ *
+ * If {@code ignoreSnapshots} is {@code true}, the version {@code 1.0.0.Final} and {@code 1.0.0.Final-SNAPSHOT} are
+ * said to be equal. If set to {@code false}, {@code 1.0.0.Final} is greater than {@code 1.0.0.Final-SNAPSHOT}.
+ *
+ *
+ * @param ignoreSnapshots {@code true} to ignore the SNAPSHOT release extension, otherwise {@code false} which
+ * values a SNAPSHOT dependency less than a non-SNAPSHOT of the same version
+ * @param v1 the first version
+ * @param v2 the second version
+ *
+ * @return {@code 0} if the versions are equal, {@code -1} if version first version is less than the second version
+ * or {@code 1} if the first version is greater than the second version
+ */
+ public static int compareVersion(final boolean ignoreSnapshots, final String v1, final String v2) {
+ // If the strings are equal ignoring the case, we can assume these are equal
+ if (Objects.requireNonNull(v1).equalsIgnoreCase(v2)) {
+ return 0;
+ }
+ final Version version1 = Version.parse(v1, ignoreSnapshots);
+ final Version version2 = Version.parse(Objects.requireNonNull(v2), ignoreSnapshots);
+ // Ensures the result is always 0, 1 or -1
+ return Integer.compare(version1.compareTo(version2), 0);
}
@Override
public int compare(final String o1, final String o2) {
- final Version v1 = Version.parse(o1);
- final Version v2 = Version.parse(o2);
- return v1.compareTo(v2);
+ return compareVersion(ignoreSnapshots, o1, o2);
}
private enum ReleaseType {
@@ -68,7 +161,7 @@ private enum ReleaseType {
map.put(alias, r);
}
}
- ENTRIES = Collections.unmodifiableMap(map);
+ ENTRIES = Map.copyOf(map);
}
private final String type;
@@ -76,14 +169,11 @@ private enum ReleaseType {
ReleaseType(final String type, final String... aliases) {
this.type = type;
- this.aliases = Collections.unmodifiableList(Arrays.asList(aliases));
+ this.aliases = List.of(aliases);
}
static ReleaseType find(final String s) {
- if (ENTRIES.containsKey(s)) {
- return ENTRIES.get(s);
- }
- return UNKNOWN;
+ return ENTRIES.getOrDefault(s, UNKNOWN);
}
}
@@ -96,7 +186,7 @@ private Version(final String original, final List parts) {
this.parts = parts;
}
- public static Version parse(final String version) {
+ static Version parse(final String version, final boolean ignoreSnapshot) {
final List parts = new ArrayList<>();
final StringBuilder sb = new StringBuilder();
boolean isDigit = false;
@@ -107,7 +197,7 @@ public static Version parse(final String version) {
if (isDigit) {
parts.add(new IntegerPart(Integer.parseInt(sb.toString())));
} else {
- parts.add(new StringPart(sb.toString()));
+ addStringPart(parts, sb, ignoreSnapshot);
}
sb.setLength(0);
isDigit = false;
@@ -116,7 +206,7 @@ public static Version parse(final String version) {
default: {
if (Character.isDigit(c)) {
if (!isDigit && sb.length() > 0) {
- parts.add(new StringPart(sb.toString()));
+ addStringPart(parts, sb, ignoreSnapshot);
sb.setLength(0);
}
isDigit = true;
@@ -135,10 +225,17 @@ public static Version parse(final String version) {
if (isDigit) {
parts.add(new IntegerPart(Integer.parseInt(sb.toString())));
} else {
- parts.add(new StringPart(sb.toString()));
+ addStringPart(parts, sb, ignoreSnapshot);
}
}
- return new Version(version, parts);
+ return new Version(version, List.copyOf(parts));
+ }
+
+ private static void addStringPart(final Collection parts, final StringBuilder sb, final boolean ignoreSnapshot) {
+ final var value = sb.toString();
+ if (!(ignoreSnapshot && ReleaseType.SNAPSHOT.type.equalsIgnoreCase(value))) {
+ parts.add(new StringPart(value));
+ }
}
@Override
@@ -151,7 +248,7 @@ public int compareTo(final Version o) {
result = left.next().compareTo(right.next());
} else if (left.hasNext()) {
result = left.next().compareTo(NULL_PART);
- } else if (right.hasNext()) {
+ } else {
// Need the inverse of the comparison
result = (-1 * right.next().compareTo(NULL_PART));
}
@@ -175,7 +272,7 @@ public boolean equals(final Object obj) {
return false;
}
final Version other = (Version) obj;
- return original.equals(other.original);
+ return Objects.equals(original, other.original);
}
@Override
@@ -183,18 +280,15 @@ public String toString() {
return original;
}
+ @FunctionalInterface
private interface Part extends Comparable {
}
- private static final Part NULL_PART = new Part() {
- @Override
- public int compareTo(final Part o) {
- throw new UnsupportedOperationException();
- }
+ private static final Part NULL_PART = o -> {
+ throw new UnsupportedOperationException();
};
private static class IntegerPart implements Part {
- private static final Integer DEFAULT_INTEGER = 0;
private final Integer value;
private IntegerPart(final Integer value) {
@@ -204,7 +298,7 @@ private IntegerPart(final Integer value) {
@Override
public int compareTo(final Part o) {
if (o == NULL_PART) {
- return value.compareTo(DEFAULT_INTEGER);
+ return value.compareTo(0);
}
if (o instanceof IntegerPart) {
return value.compareTo(((IntegerPart) o).value);
diff --git a/src/test/java/org/wildfly/plugin/tools/VersionTestCase.java b/src/test/java/org/wildfly/plugin/tools/VersionTestCase.java
index e8f4e9c..2aa7bf9 100644
--- a/src/test/java/org/wildfly/plugin/tools/VersionTestCase.java
+++ b/src/test/java/org/wildfly/plugin/tools/VersionTestCase.java
@@ -34,6 +34,16 @@ public void testGetLatest() {
compareLatest("7.5.Final", "7.1.1.Final", "7.1.3.Final", "7.5.Final", "7.4.Final", "7.5.Final-SNAPSHOT");
}
+ @Test
+ public void ignoreSnapshot() {
+ Assertions.assertEquals(0, VersionComparator.compareVersion(true, "1.0.0.Final-SNAPSHOT", "1.0.0.Final"));
+ Assertions.assertEquals(0, VersionComparator.compareVersion(true, "10.11.0.Alpha1-SNAPSHOT", "10.11.0.a1-SNAPSHOT"));
+ Assertions.assertEquals(0, VersionComparator.compareVersion(true, "15.0.0.ga", "15.0.0.Final-SNAPSHOT"));
+ Assertions.assertEquals(1, VersionComparator.compareVersion(true, "1.0.1.Final-SNAPSHOT", "1.0.0.Final"));
+ Assertions.assertEquals(1, VersionComparator.compareVersion(true, "12.0.2.Final-SNAPSHOT", "12.0.2.Beta1"));
+ Assertions.assertEquals(-1, VersionComparator.compareVersion(true, "12.0.1.Final-SNAPSHOT", "12.0.2.Alpha1-SNAPSHOT"));
+ }
+
@Test
public void testSortOrder() {
// Define a list in the expected order
@@ -62,12 +72,12 @@ public void testSortOrder() {
// All entries should in the same order
Assertions.assertTrue(orderedVersions.containsAll(versions));
- versions.sort(new VersionComparator());
+ versions.sort(VersionComparator.getInstance());
Assertions.assertEquals(orderedVersions, versions);
}
private void compareLatest(final String expected, final String... versions) {
- final SortedSet set = new TreeSet<>(new VersionComparator());
+ final SortedSet set = new TreeSet<>(VersionComparator.getInstance());
set.addAll(Arrays.asList(versions));
Assertions.assertEquals(expected, set.last());
}
From d891591fba247fcea65dfb8ae19a0eea25f8364e Mon Sep 17 00:00:00 2001
From: "James R. Perkins"
Date: Fri, 22 Mar 2024 10:23:36 -0700
Subject: [PATCH 2/2] Fix the CI name.
Signed-off-by: James R. Perkins
---
.github/workflows/ci.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index afb00be..00ff078 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,7 +1,7 @@
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
-name: WildFly Maven Plugin - CI
+name: WildFly Plugin Tools - CI
on:
push:
@@ -38,7 +38,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- os: [ubuntu-latest, windows-latest ]
+ os: [ 'ubuntu-latest' , 'windows-latest' ]
java: ['11', '17', '21']
steps: