You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by mc...@apache.org on 2021/07/09 09:34:27 UTC

[cassandra-in-jvm-dtest-api] 02/02: Introduce SemVer4j for version representation, parsing and handling

This is an automated email from the ASF dual-hosted git repository.

mck pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra-in-jvm-dtest-api.git

commit 0a13871f9dc8261b3defc1183eb4eee92d9c4f72
Author: mck <mc...@apache.org>
AuthorDate: Sat May 15 23:53:38 2021 +0200

    Introduce SemVer4j for version representation, parsing and handling
    
     patch by Mick Semb Wever; reviewed by Alex Petrov for CASSANDRA-16649
---
 pom.xml                                            |   5 +
 .../cassandra/distributed/api/IInstanceConfig.java |   5 +-
 .../cassandra/distributed/shared/Versions.java     | 134 +++++++--------------
 .../cassandra/distributed/shared/VersionsTest.java |   4 +-
 4 files changed, 54 insertions(+), 94 deletions(-)

diff --git a/pom.xml b/pom.xml
index 88cb573..bfc2d8c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -50,6 +50,11 @@
             <artifactId>slf4j-api</artifactId>
             <version>1.7.25</version>
         </dependency>
+        <dependency>
+            <groupId>com.vdurmont</groupId>
+            <artifactId>semver4j</artifactId>
+            <version>3.1.0</version>
+        </dependency>
 
         <dependency>
             <groupId>org.junit.jupiter</groupId>
diff --git a/src/main/java/org/apache/cassandra/distributed/api/IInstanceConfig.java b/src/main/java/org/apache/cassandra/distributed/api/IInstanceConfig.java
index 7324816..ba1a09b 100644
--- a/src/main/java/org/apache/cassandra/distributed/api/IInstanceConfig.java
+++ b/src/main/java/org/apache/cassandra/distributed/api/IInstanceConfig.java
@@ -25,8 +25,9 @@ import java.util.Objects;
 import java.util.UUID;
 import java.util.function.Function;
 
+import com.vdurmont.semver4j.Semver;
+
 import org.apache.cassandra.distributed.shared.NetworkTopology;
-import org.apache.cassandra.distributed.shared.Versions;
 
 public interface IInstanceConfig
 {
@@ -68,7 +69,7 @@ public interface IInstanceConfig
 
     boolean has(Feature featureFlag);
 
-    public IInstanceConfig forVersion(Versions.Major major);
+    public IInstanceConfig forVersion(Semver series);
 
     public static class ParameterizedClass
     {
diff --git a/src/main/java/org/apache/cassandra/distributed/shared/Versions.java b/src/main/java/org/apache/cassandra/distributed/shared/Versions.java
index a49b7c7..1fb7149 100644
--- a/src/main/java/org/apache/cassandra/distributed/shared/Versions.java
+++ b/src/main/java/org/apache/cassandra/distributed/shared/Versions.java
@@ -24,7 +24,6 @@ import java.net.URL;
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -32,6 +31,8 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
+import com.vdurmont.semver4j.Semver;
+import com.vdurmont.semver4j.Semver.SemverType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -64,112 +65,64 @@ public final class Versions
         return urls;
     }
 
-    public enum Major
+    public static final class Version implements Comparable<Version>
     {
-        v22("2\\.2\\.([0-9]+)"),
-        v30("3\\.0\\.([0-9]+)"),
-        v3X("3\\.([1-9]|1[01])(\\.([0-9]+))?"),
-        v40("4\\.0(?:\\.|-alpha|-beta|-rc)([0-9]+)(\\.([0-9]+))?"),
-        v4X("4\\.([1-9][0-9]*)(\\.([0-9]+))?");
-        final Pattern pattern;
-
-        Major(String verify)
-        {
-            this.pattern = Pattern.compile(verify);
-        }
-
-        static Major fromFull(String version)
-        {
-            if (version.isEmpty())
-                throw new IllegalArgumentException(version);
-            switch (version.charAt(0))
-            {
-                case '2':
-                    if (version.startsWith("2.2"))
-                        return v22;
-                    throw new IllegalArgumentException(version);
-                case '3':
-                    if (version.startsWith("3.0"))
-                        return v30;
-                    return v3X;
-                case '4':
-                    if (version.startsWith("4.0"))
-                        return v40;
-                    return v4X;
-                default:
-                    throw new IllegalArgumentException(version);
-            }
-        }
-
-        // verify that the version string is valid for this major version
-        boolean verify(String version)
-        {
-            return pattern.matcher(version).matches();
-        }
-
-        // sort two strings of the same major version as this enum instance
-        int compare(String a, String b)
-        {
-            Matcher ma = pattern.matcher(a);
-            Matcher mb = pattern.matcher(b);
-            if (!ma.matches()) throw new IllegalArgumentException(a);
-            if (!mb.matches()) throw new IllegalArgumentException(b);
-            int result = Integer.compare(Integer.parseInt(ma.group(1)), Integer.parseInt(mb.group(1)));
-            if (result == 0 && this == v3X && (ma.group(3) != null || mb.group(3) != null))
-            {
-                if (ma.group(3) != null && mb.group(3) != null)
-                {
-                    // XXX likely wrong for alpha|beta|rc versions
-                    result = Integer.compare(Integer.parseInt(ma.group(3)), Integer.parseInt(mb.group(3)));
-                }
-                else
-                {
-                    result = ma.group(3) != null ? 1 : -1;
-                }
-            }
-            // sort descending
-            return -result;
-        }
-    }
-
-    public static class Version
-    {
-        public final Major major;
-        public final String version;
+        public final Semver version;
         public final URL[] classpath;
 
         public Version(String version, URL[] classpath)
         {
-            this(Major.fromFull(version), version, classpath);
+            this(new Semver(version, SemverType.LOOSE), classpath);
         }
 
-        public Version(Major major, String version, URL[] classpath)
+        public Version(Semver version, URL[] classpath)
         {
-            this.major = major;
             this.version = version;
             this.classpath = classpath;
         }
+
+        @Override
+        public int compareTo(Version o) {
+            return version.compareTo(o.version);
+        }
     }
 
-    private final Map<Major, List<Version>> versions;
+    private final Map<Semver, List<Version>> versions;
 
-    private Versions(Map<Major, List<Version>> versions)
+    private Versions(Map<Semver, List<Version>> versions)
     {
         this.versions = versions;
     }
 
     public Version get(String full)
     {
-        return versions.get(Major.fromFull(full))
+        return get(new Semver(full, SemverType.LOOSE));
+    }
+
+    public Version get(Semver version)
+    {
+        return versions.get(first(version))
                        .stream()
-                       .filter(v -> full.equals(v.version))
+                       .filter(v -> version.equals(v.version))
                        .findFirst()
-                       .orElseThrow(() -> new RuntimeException("No version " + full + " found"));
+                       .orElseThrow(() -> new RuntimeException("No version " + version.getOriginalValue() + " found"));
+    }
+
+    private static Semver first(Semver version)
+    {
+        int major = version.getMajor();
+        int minor = version.getMinor();
+        if (major < 2 || (major < 3 && minor < 1))
+            throw new IllegalArgumentException(version.getOriginalValue());
+        return new Semver(major + "." + minor, SemverType.LOOSE);
     }
 
-    public Version getLatest(Major major)
+    public Version getLatest(Semver version)
     {
-        return versions.get(major).stream().findFirst().orElseThrow(() -> new RuntimeException("No " + major + " versions found"));
+        return versions.get(first(version))
+											  .stream()
+												.findFirst()
+											  .orElseThrow(() -> new RuntimeException("No " + version + " versions found"));
     }
 
     public static Versions find()
@@ -178,9 +131,7 @@ public final class Versions
         final File sourceDirectory = new File(dtestJarDirectory);
         logger.info("Looking for dtest jars in " + sourceDirectory.getAbsolutePath());
         final Pattern pattern = Pattern.compile("dtest-(?<fullversion>(\\d+)\\.(\\d+)((\\.|-alpha|-beta|-rc)([0-9]+))?(\\.\\d+)?)([~\\-]\\w[.\\w]*(?:\\-\\w[.\\w]*)*)?(\\+[.\\w]+)?\\.jar");
-        final Map<Major, List<Version>> versions = new HashMap<>();
-        for (Major major : Major.values())
-            versions.put(major, new ArrayList<>());
+        final Map<Semver, List<Version>> versions = new HashMap<>();
 
         if (sourceDirectory.exists())
         {
@@ -189,18 +140,19 @@ public final class Versions
                 Matcher m = pattern.matcher(file.getName());
                 if (!m.matches())
                     continue;
-                String version = m.group(1);
-                Major major = Major.fromFull(version);
-                versions.get(major).add(new Version(major, version, new URL[]{ toURL(file) }));
+                Semver version = new Semver(m.group(1), SemverType.LOOSE);
+                Semver series = first(version);
+                versions.putIfAbsent(series, new ArrayList<>());
+                versions.get(series).add(new Version(version, new URL[]{ toURL(file) }));
             }
         }
 
-        for (Map.Entry<Major, List<Version>> e : versions.entrySet())
+        for (Map.Entry<Semver, List<Version>> e : versions.entrySet())
         {
             if (e.getValue().isEmpty())
                 continue;
-            Collections.sort(e.getValue(), Comparator.comparing(v -> v.version, e.getKey()::compare));
-            System.out.println("Found " + e.getValue().stream().map(v -> v.version).collect(Collectors.joining(", ")));
+            Collections.sort(e.getValue(), Collections.reverseOrder());
+            System.out.println("Found " + e.getValue().stream().map(v -> v.version.getOriginalValue()).collect(Collectors.joining(", ")));
         }
 
         return new Versions(versions);
diff --git a/src/test/java/org/apache/cassandra/distributed/shared/VersionsTest.java b/src/test/java/org/apache/cassandra/distributed/shared/VersionsTest.java
index e929ade..0bdb57e 100644
--- a/src/test/java/org/apache/cassandra/distributed/shared/VersionsTest.java
+++ b/src/test/java/org/apache/cassandra/distributed/shared/VersionsTest.java
@@ -19,6 +19,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
+import com.vdurmont.semver4j.Semver;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -75,7 +76,8 @@ public class VersionsTest
     @Test
     public void testGetLatest()
     {
-        Versions.find().getLatest(Versions.Major.v22);
+        Versions.find().getLatest(new Semver("2.2.0"));
+        Versions.find().getLatest(new Semver("2.2", Semver.SemverType.LOOSE));
     }
 
     @Test

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org