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

sjaranowski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-release.git


The following commit(s) were added to refs/heads/master by this push:
     new 88630f90 Fixed #1426 : Replace archived `org.semver:api` with custom 
`SemVer` implementation (#1430)
88630f90 is described below

commit 88630f903c60b170f3cd04325a4842182ce7d30a
Author: Harsh Mehta <[email protected]>
AuthorDate: Sun Nov 30 16:46:33 2025 +0530

    Fixed #1426 : Replace archived `org.semver:api` with custom `SemVer` 
implementation (#1430)
    
    
    Signed-off-by: Harsh Mehta <[email protected]>
    Co-authored-by: harsh-mehta-sb <[email protected]>
---
 .../maven-release-semver-policy/pom.xml            |  24 --
 .../policy/semver/AbstractSemVerVersionPolicy.java |  11 +-
 .../maven/shared/release/policy/semver/SemVer.java | 252 +++++++++++++++++++++
 .../SemVerMajorDevelopmentVersionPolicy.java       |   5 +-
 .../semver/SemVerMajorReleaseVersionPolicy.java    |   5 +-
 .../SemVerMinorDevelopmentVersionPolicy.java       |   5 +-
 .../semver/SemVerMinorReleaseVersionPolicy.java    |   5 +-
 .../SemVerPatchDevelopmentVersionPolicy.java       |   5 +-
 .../shared/release/policy/semver/SemVerTest.java   | 147 ++++++++++++
 9 files changed, 414 insertions(+), 45 deletions(-)

diff --git a/maven-release-policies/maven-release-semver-policy/pom.xml 
b/maven-release-policies/maven-release-semver-policy/pom.xml
index 64b29079..19ff5742 100644
--- a/maven-release-policies/maven-release-semver-policy/pom.xml
+++ b/maven-release-policies/maven-release-semver-policy/pom.xml
@@ -39,30 +39,6 @@ under the License.
       <version>${project.parent.version}</version>
       <scope>provided</scope>
     </dependency>
-    <dependency>
-      <groupId>org.semver</groupId>
-      <artifactId>api</artifactId>
-      <version>0.9.33</version>
-      <exclusions>
-        <!-- only one class Version from semver api is used, avoid bringing in 
unnecessary dependencies -->
-        <exclusion>
-          <groupId>junit</groupId>
-          <artifactId>junit</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.ow2.asm</groupId>
-          <artifactId>*</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>de.tototec</groupId>
-          <artifactId>de.tototec.cmdoption</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>com.google.code.findbugs</groupId>
-          <artifactId>jsr305</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
 
     <dependency>
       <groupId>javax.inject</groupId>
diff --git 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/AbstractSemVerVersionPolicy.java
 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/AbstractSemVerVersionPolicy.java
index 7b6b8037..ce30c2ee 100644
--- 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/AbstractSemVerVersionPolicy.java
+++ 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/AbstractSemVerVersionPolicy.java
@@ -22,7 +22,6 @@ import 
org.apache.maven.shared.release.policy.version.VersionPolicy;
 import org.apache.maven.shared.release.policy.version.VersionPolicyRequest;
 import org.apache.maven.shared.release.policy.version.VersionPolicyResult;
 import org.apache.maven.shared.release.versions.VersionParseException;
-import org.semver.Version;
 
 /**
  * Abstract base class for SemVer-based VersionPolicy implementations.
@@ -31,19 +30,19 @@ import org.semver.Version;
  */
 abstract class AbstractSemVerVersionPolicy implements VersionPolicy {
 
-    protected Version createVersionFromRequest(VersionPolicyRequest request) 
throws VersionParseException {
+    protected SemVer createVersionFromRequest(VersionPolicyRequest request) 
throws VersionParseException {
         try {
-            return Version.parse(request.getVersion());
+            return SemVer.parse(request.getVersion());
         } catch (IllegalArgumentException e) {
             throw new VersionParseException(e.getMessage());
         }
     }
 
-    protected VersionPolicyResult createResult(Version version) {
+    protected VersionPolicyResult createResult(SemVer version) {
         return new VersionPolicyResult().setVersion(version.toString());
     }
 
-    protected VersionPolicyResult createSnapshotResult(Version version) {
-        return new VersionPolicyResult().setVersion(version.toString() + 
"-SNAPSHOT");
+    protected VersionPolicyResult createSnapshotResult(SemVer version) {
+        return new 
VersionPolicyResult().setVersion(version.toSnapshotVersion().toString());
     }
 }
diff --git 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVer.java
 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVer.java
new file mode 100644
index 00000000..ff88098b
--- /dev/null
+++ 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVer.java
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.shared.release.policy.semver;
+
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A simple Semantic Versioning 2.0.0 implementation.
+ * <p>
+ * This class provides basic parsing and manipulation of semantic version 
strings
+ * following the format: MAJOR.MINOR.PATCH[-PRERELEASE][+METADATA]
+ * </p>
+ *
+ * @see <a href="https://semver.org/";>Semantic Versioning 2.0.0</a>
+ */
+class SemVer {
+
+    /**
+     * Regex pattern for parsing semantic versions from semver.org.
+     * Groups: 1=major, 2=minor, 3=patch, 4=prerelease, 5=metadata
+     *
+     * @see <a 
href="https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string";>SemVer
 Regex</a>
+     */
+    private static final Pattern SEMVER_PATTERN = 
Pattern.compile("^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)"
+            + "(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)"
+            + 
"(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$");
+
+    private final int major;
+    private final int minor;
+    private final int patch;
+    private final String preRelease;
+    private final String metadata;
+
+    /**
+     * Version element types that can be incremented.
+     */
+    public enum Element {
+        MAJOR,
+        MINOR,
+        PATCH
+    }
+
+    /**
+     * Constructs a new SemVer instance.
+     *
+     * @param major the major version number
+     * @param minor the minor version number
+     * @param patch the patch version number
+     * @param preRelease the pre-release identifier (can be null)
+     * @param metadata the build metadata (can be null)
+     */
+    protected SemVer(int major, int minor, int patch, String preRelease, 
String metadata) {
+        if (major < 0 || minor < 0 || patch < 0) {
+            throw new IllegalArgumentException("Version numbers must be 
non-negative");
+        }
+        this.major = major;
+        this.minor = minor;
+        this.patch = patch;
+        this.preRelease = preRelease;
+        this.metadata = metadata;
+    }
+
+    /**
+     * Parses a version string into a SemVer object.
+     *
+     * @param version the version string to parse
+     * @return the parsed SemVer object
+     * @throws IllegalArgumentException if the version string is invalid
+     */
+    static SemVer parse(String version) {
+        if (version == null || version.trim().isEmpty()) {
+            throw new IllegalArgumentException("Version string cannot be null 
or empty");
+        }
+
+        Matcher matcher = SEMVER_PATTERN.matcher(version.trim());
+        if (!matcher.matches()) {
+            throw new IllegalArgumentException("Invalid semantic version 
format: " + version);
+        }
+
+        int major = Integer.parseInt(matcher.group(1));
+        int minor = Integer.parseInt(matcher.group(2));
+        int patch = Integer.parseInt(matcher.group(3));
+        String preRelease = matcher.group(4);
+        String metadata = matcher.group(5);
+
+        return new SemVer(major, minor, patch, preRelease, metadata);
+    }
+
+    /**
+     * Returns a new SemVer with the release version (removes -SNAPSHOT and 
any pre-release/metadata).
+     * <p>
+     * Examples:
+     * <ul>
+     *   <li>1.2.3-SNAPSHOT → 1.2.3</li>
+     *   <li>1.2.3-beta+build → 1.2.3</li>
+     *   <li>1.2.3 → 1.2.3</li>
+     * </ul>
+     *
+     * @return a new SemVer representing the release version
+     */
+    SemVer toReleaseVersion() {
+        return new SemVer(major, minor, patch, null, null);
+    }
+
+    /**
+     * Returns a new SemVer with -SNAPSHOT appended as pre-release identifier.
+     * If the version already has a pre-release identifier, it will be 
replaced with SNAPSHOT.
+     * Metadata is removed.
+     * <p>
+     * Examples:
+     * <ul>
+     *   <li>1.2.3 → 1.2.3-SNAPSHOT</li>
+     *   <li>1.2.3-beta → 1.2.3-SNAPSHOT</li>
+     *   <li>1.2.3+build → 1.2.3-SNAPSHOT</li>
+     *   <li>1.2.3-SNAPSHOT → 1.2.3-SNAPSHOT (no change)</li>
+     * </ul>
+     *
+     * @return a new SemVer with SNAPSHOT pre-release identifier, or this 
instance if already a SNAPSHOT version
+     */
+    SemVer toSnapshotVersion() {
+        if ("SNAPSHOT".equals(preRelease) && metadata == null) {
+            return this;
+        }
+        return new SemVer(major, minor, patch, "SNAPSHOT", null);
+    }
+
+    /**
+     * Returns a new SemVer with the specified element incremented.
+     * If the version has pre-release or metadata, returns the release version 
without incrementing.
+     * Otherwise, increments the specified element and all lower elements are 
reset to 0.
+     * Pre-release and metadata are always cleared in the result.
+     *
+     * @param element the element to increment (MAJOR, MINOR, or PATCH)
+     * @return a new SemVer with the specified element incremented (or release 
version if pre-release/metadata present)
+     */
+    SemVer next(Element element) {
+        Objects.requireNonNull(element, "Element cannot be null");
+
+        // If version has pre-release or metadata, just return release version 
without incrementing
+        if (hasPreRelease() || hasMetadata()) {
+            return toReleaseVersion();
+        }
+
+        switch (element) {
+            case MAJOR:
+                return new SemVer(major + 1, 0, 0, null, null);
+            case MINOR:
+                return new SemVer(major, minor + 1, 0, null, null);
+            case PATCH:
+                return new SemVer(major, minor, patch + 1, null, null);
+            default:
+                throw new IllegalArgumentException("Unknown element: " + 
element);
+        }
+    }
+
+    /**
+     * Checks if this version has a pre-release identifier.
+     *
+     * @return true if pre-release identifier is present, false otherwise
+     */
+    private boolean hasPreRelease() {
+        return preRelease != null && !preRelease.isEmpty();
+    }
+
+    /**
+     * Checks if this version has build metadata.
+     *
+     * @return true if build metadata is present, false otherwise
+     */
+    private boolean hasMetadata() {
+        return metadata != null && !metadata.isEmpty();
+    }
+
+    /**
+     * Returns the major version number.
+     *
+     * @return the major version
+     */
+    int getMajor() {
+        return major;
+    }
+
+    /**
+     * Returns the minor version number.
+     *
+     * @return the minor version
+     */
+    int getMinor() {
+        return minor;
+    }
+
+    /**
+     * Returns the patch version number.
+     *
+     * @return the patch version
+     */
+    int getPatch() {
+        return patch;
+    }
+
+    /**
+     * Returns the pre-release identifier.
+     *
+     * @return the pre-release identifier, or null if not present
+     */
+    String getPreRelease() {
+        return preRelease;
+    }
+
+    /**
+     * Returns the build metadata.
+     *
+     * @return the build metadata, or null if not present
+     */
+    String getMetadata() {
+        return metadata;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(major).append('.').append(minor).append('.').append(patch);
+
+        if (preRelease != null && !preRelease.isEmpty()) {
+            sb.append('-').append(preRelease);
+        }
+
+        if (metadata != null && !metadata.isEmpty()) {
+            sb.append('+').append(metadata);
+        }
+
+        return sb.toString();
+    }
+}
diff --git 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMajorDevelopmentVersionPolicy.java
 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMajorDevelopmentVersionPolicy.java
index 567947a6..2bdb8012 100644
--- 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMajorDevelopmentVersionPolicy.java
+++ 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMajorDevelopmentVersionPolicy.java
@@ -24,7 +24,6 @@ import javax.inject.Singleton;
 import org.apache.maven.shared.release.policy.version.VersionPolicyRequest;
 import org.apache.maven.shared.release.policy.version.VersionPolicyResult;
 import org.apache.maven.shared.release.versions.VersionParseException;
-import org.semver.Version;
 
 /**
  * Uses SemVer implementation to increase major element when resolving the 
development version.
@@ -37,13 +36,13 @@ class SemVerMajorDevelopmentVersionPolicy extends 
AbstractSemVerVersionPolicy {
 
     @Override
     public VersionPolicyResult getReleaseVersion(VersionPolicyRequest request) 
throws VersionParseException {
-        Version version = createVersionFromRequest(request).toReleaseVersion();
+        SemVer version = createVersionFromRequest(request).toReleaseVersion();
         return createResult(version);
     }
 
     @Override
     public VersionPolicyResult getDevelopmentVersion(VersionPolicyRequest 
request) throws VersionParseException {
-        Version version = 
createVersionFromRequest(request).next(Version.Element.MAJOR);
+        SemVer version = 
createVersionFromRequest(request).next(SemVer.Element.MAJOR);
         return createSnapshotResult(version);
     }
 }
diff --git 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMajorReleaseVersionPolicy.java
 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMajorReleaseVersionPolicy.java
index b2c97960..09ecc784 100644
--- 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMajorReleaseVersionPolicy.java
+++ 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMajorReleaseVersionPolicy.java
@@ -24,7 +24,6 @@ import javax.inject.Singleton;
 import org.apache.maven.shared.release.policy.version.VersionPolicyRequest;
 import org.apache.maven.shared.release.policy.version.VersionPolicyResult;
 import org.apache.maven.shared.release.versions.VersionParseException;
-import org.semver.Version;
 
 /**
  * Uses SemVer implementation to increase major element when resolving the 
release version.
@@ -37,13 +36,13 @@ class SemVerMajorReleaseVersionPolicy extends 
AbstractSemVerVersionPolicy {
 
     @Override
     public VersionPolicyResult getReleaseVersion(VersionPolicyRequest request) 
throws VersionParseException {
-        Version version = 
createVersionFromRequest(request).toReleaseVersion().next(Version.Element.MAJOR);
+        SemVer version = 
createVersionFromRequest(request).toReleaseVersion().next(SemVer.Element.MAJOR);
         return createResult(version);
     }
 
     @Override
     public VersionPolicyResult getDevelopmentVersion(VersionPolicyRequest 
request) throws VersionParseException {
-        Version version = 
createVersionFromRequest(request).next(Version.Element.PATCH);
+        SemVer version = 
createVersionFromRequest(request).next(SemVer.Element.PATCH);
         return createSnapshotResult(version);
     }
 }
diff --git 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMinorDevelopmentVersionPolicy.java
 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMinorDevelopmentVersionPolicy.java
index 573e6f99..0fa7d816 100644
--- 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMinorDevelopmentVersionPolicy.java
+++ 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMinorDevelopmentVersionPolicy.java
@@ -24,7 +24,6 @@ import javax.inject.Singleton;
 import org.apache.maven.shared.release.policy.version.VersionPolicyRequest;
 import org.apache.maven.shared.release.policy.version.VersionPolicyResult;
 import org.apache.maven.shared.release.versions.VersionParseException;
-import org.semver.Version;
 
 /**
  * Uses SemVer implementation to increase minor element when resolving the 
development version.
@@ -37,13 +36,13 @@ class SemVerMinorDevelopmentVersionPolicy extends 
AbstractSemVerVersionPolicy {
 
     @Override
     public VersionPolicyResult getReleaseVersion(VersionPolicyRequest request) 
throws VersionParseException {
-        Version version = createVersionFromRequest(request).toReleaseVersion();
+        SemVer version = createVersionFromRequest(request).toReleaseVersion();
         return createResult(version);
     }
 
     @Override
     public VersionPolicyResult getDevelopmentVersion(VersionPolicyRequest 
request) throws VersionParseException {
-        Version version = 
createVersionFromRequest(request).next(Version.Element.MINOR);
+        SemVer version = 
createVersionFromRequest(request).next(SemVer.Element.MINOR);
         return createSnapshotResult(version);
     }
 }
diff --git 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMinorReleaseVersionPolicy.java
 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMinorReleaseVersionPolicy.java
index 951c706a..66426d81 100644
--- 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMinorReleaseVersionPolicy.java
+++ 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerMinorReleaseVersionPolicy.java
@@ -24,7 +24,6 @@ import javax.inject.Singleton;
 import org.apache.maven.shared.release.policy.version.VersionPolicyRequest;
 import org.apache.maven.shared.release.policy.version.VersionPolicyResult;
 import org.apache.maven.shared.release.versions.VersionParseException;
-import org.semver.Version;
 
 /**
  * Uses SemVer implementation to increase minor element when resolving the 
release version.
@@ -37,13 +36,13 @@ class SemVerMinorReleaseVersionPolicy extends 
AbstractSemVerVersionPolicy {
 
     @Override
     public VersionPolicyResult getReleaseVersion(VersionPolicyRequest request) 
throws VersionParseException {
-        Version version = 
createVersionFromRequest(request).toReleaseVersion().next(Version.Element.MINOR);
+        SemVer version = 
createVersionFromRequest(request).toReleaseVersion().next(SemVer.Element.MINOR);
         return createResult(version);
     }
 
     @Override
     public VersionPolicyResult getDevelopmentVersion(VersionPolicyRequest 
request) throws VersionParseException {
-        Version version = 
createVersionFromRequest(request).next(Version.Element.PATCH);
+        SemVer version = 
createVersionFromRequest(request).next(SemVer.Element.PATCH);
         return createSnapshotResult(version);
     }
 }
diff --git 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerPatchDevelopmentVersionPolicy.java
 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerPatchDevelopmentVersionPolicy.java
index f0b8e75b..70cdd886 100644
--- 
a/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerPatchDevelopmentVersionPolicy.java
+++ 
b/maven-release-policies/maven-release-semver-policy/src/main/java/org/apache/maven/shared/release/policy/semver/SemVerPatchDevelopmentVersionPolicy.java
@@ -24,7 +24,6 @@ import javax.inject.Singleton;
 import org.apache.maven.shared.release.policy.version.VersionPolicyRequest;
 import org.apache.maven.shared.release.policy.version.VersionPolicyResult;
 import org.apache.maven.shared.release.versions.VersionParseException;
-import org.semver.Version;
 
 /**
  * Uses SemVer implementation to increase patch element when resolving the 
development version.
@@ -37,13 +36,13 @@ class SemVerPatchDevelopmentVersionPolicy extends 
AbstractSemVerVersionPolicy {
 
     @Override
     public VersionPolicyResult getReleaseVersion(VersionPolicyRequest request) 
throws VersionParseException {
-        Version version = createVersionFromRequest(request).toReleaseVersion();
+        SemVer version = createVersionFromRequest(request).toReleaseVersion();
         return createResult(version);
     }
 
     @Override
     public VersionPolicyResult getDevelopmentVersion(VersionPolicyRequest 
request) throws VersionParseException {
-        Version version = 
createVersionFromRequest(request).next(Version.Element.PATCH);
+        SemVer version = 
createVersionFromRequest(request).next(SemVer.Element.PATCH);
         return createSnapshotResult(version);
     }
 }
diff --git 
a/maven-release-policies/maven-release-semver-policy/src/test/java/org/apache/maven/shared/release/policy/semver/SemVerTest.java
 
b/maven-release-policies/maven-release-semver-policy/src/test/java/org/apache/maven/shared/release/policy/semver/SemVerTest.java
new file mode 100644
index 00000000..8110052f
--- /dev/null
+++ 
b/maven-release-policies/maven-release-semver-policy/src/test/java/org/apache/maven/shared/release/policy/semver/SemVerTest.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.shared.release.policy.semver;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/**
+ * Unit tests for the SemVer class.
+ */
+class SemVerTest {
+
+    @ParameterizedTest
+    @CsvSource({
+        "'1.2.3', 1, 2, 3, , , '1.2.3'",
+        "'1.2.3-alpha.1', 1, 2, 3, 'alpha.1', , '1.2.3-alpha.1'",
+        "'1.2.3+build.123', 1, 2, 3, , 'build.123', '1.2.3+build.123'",
+        "'1.2.3-beta.2+build.456', 1, 2, 3, 'beta.2', 'build.456', 
'1.2.3-beta.2+build.456'",
+        "'1.0.0-SNAPSHOT', 1, 0, 0, 'SNAPSHOT', , '1.0.0-SNAPSHOT'",
+        "'  1.2.3  ', 1, 2, 3, , , '1.2.3'",
+        "'0.0.0', 0, 0, 0, , , '0.0.0'",
+        "'123.456.789', 123, 456, 789, , , '123.456.789'"
+    })
+    void testParseVersion(
+            String version,
+            int expectedMajor,
+            int expectedMinor,
+            int expectedPatch,
+            String expectedPreRelease,
+            String expectedMetadata,
+            String expectedToString) {
+        SemVer semVer = SemVer.parse(version);
+        assertEquals(expectedMajor, semVer.getMajor());
+        assertEquals(expectedMinor, semVer.getMinor());
+        assertEquals(expectedPatch, semVer.getPatch());
+        assertEquals(expectedPreRelease, semVer.getPreRelease());
+        assertEquals(expectedMetadata, semVer.getMetadata());
+        assertEquals(expectedToString, semVer.toString());
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = {"invalid", "1.2", "1.2.3.4", ""})
+    void testParseInvalidVersionThrowsException(String invalidVersion) {
+        assertThrows(IllegalArgumentException.class, () -> 
SemVer.parse(invalidVersion));
+    }
+
+    @Test
+    void testParseNullVersionThrowsException() {
+        assertThrows(IllegalArgumentException.class, () -> SemVer.parse(null));
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+        "'1.2.3-SNAPSHOT', '1.2.3'",
+        "'1.2.3-beta+build', '1.2.3'",
+        "'1.0.0-alpha', '1.0.0'",
+        "'2.1.5+metadata', '2.1.5'"
+    })
+    void testToReleaseVersion(String input, String expected) {
+        SemVer version = SemVer.parse(input);
+        SemVer releaseVersion = version.toReleaseVersion();
+        assertEquals(expected, releaseVersion.toString());
+        assertNull(releaseVersion.getPreRelease());
+        assertNull(releaseVersion.getMetadata());
+    }
+
+    @ParameterizedTest
+    @CsvSource({"MAJOR, '2.0.0', 2, 0, 0", "MINOR, '1.3.0', 1, 3, 0", "PATCH, 
'1.2.4', 1, 2, 4"})
+    void testNext(
+            SemVer.Element element, String expectedVersion, int expectedMajor, 
int expectedMinor, int expectedPatch) {
+        SemVer version = SemVer.parse("1.2.3");
+        SemVer next = version.next(element);
+        assertEquals(expectedVersion, next.toString());
+        assertEquals(expectedMajor, next.getMajor());
+        assertEquals(expectedMinor, next.getMinor());
+        assertEquals(expectedPatch, next.getPatch());
+    }
+
+    @Test
+    void testNextClearsPreReleaseAndMetadata() {
+        SemVer version = SemVer.parse("1.2.3-beta+build");
+        SemVer next = version.next(SemVer.Element.MINOR);
+        assertEquals("1.2.3", next.toString());
+        assertNull(next.getPreRelease());
+        assertNull(next.getMetadata());
+    }
+
+    @Test
+    void testNextWithNullElementThrowsException() {
+        SemVer version = SemVer.parse("1.2.3");
+        assertThrows(NullPointerException.class, () -> version.next(null));
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+        "'1.2.3', '1.2.3-SNAPSHOT', 'SNAPSHOT', , false",
+        "'1.0.0', '1.0.0-SNAPSHOT', 'SNAPSHOT', , false",
+        "'1.2.3-beta.1', '1.2.3-SNAPSHOT', 'SNAPSHOT', , false",
+        "'1.2.3-SNAPSHOT', '1.2.3-SNAPSHOT', 'SNAPSHOT', , true"
+    })
+    void testToSnapshotVersion(
+            String input,
+            String expectedVersion,
+            String expectedPreRelease,
+            String expectedMetadata,
+            boolean shouldBeSameObject) {
+        SemVer version = SemVer.parse(input);
+        SemVer snapshotVersion = version.toSnapshotVersion();
+        assertEquals(expectedVersion, snapshotVersion.toString());
+        assertEquals(expectedPreRelease, snapshotVersion.getPreRelease());
+        assertEquals(expectedMetadata, snapshotVersion.getMetadata());
+
+        // For the already snapshot case, verify it returns the same object
+        if (shouldBeSameObject) {
+            assertSame(version, snapshotVersion);
+        }
+    }
+
+    @ParameterizedTest
+    @CsvSource({"-1, 0, 0", "0, -1, 0", "0, 0, -1"})
+    void testConstructorValidation(int major, int minor, int patch) {
+        assertThrows(IllegalArgumentException.class, () -> new SemVer(major, 
minor, patch, null, null));
+    }
+}

Reply via email to