diff --git a/src/main/java/com/github/zafarkhaja/semver/Version.java b/src/main/java/com/github/zafarkhaja/semver/Version.java index 01dc052..8fb8d68 100644 --- a/src/main/java/com/github/zafarkhaja/semver/Version.java +++ b/src/main/java/com/github/zafarkhaja/semver/Version.java @@ -23,6 +23,7 @@ */ package com.github.zafarkhaja.semver; +import java.util.Comparator; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -103,6 +104,34 @@ public class Version implements Comparable { } } + public static final Comparator BUILD_AWARE_ORDER = new BuildAwareOrder(); + + private static class BuildAwareOrder implements Comparator { + + @Override + public int compare(Version v1, Version v2) { + int result = v1.compareTo(v2); + if (result == 0) { + result = compareBuilds(v1, v2); + } + return result; + } + + private int compareBuilds(Version v1, Version v2) { + int result = 0; + if (v1.build != null && v2.build != null) { + result = v1.build.compareTo(v2.build); + } else if (v1.build == null ^ v2.build == null) { + /** + * Build versions satisfy and have a higher precedence + * than the associated normal version. + */ + result = (v1.build == null) ? -1 : 1; + } + return result; + } + } + Version(NormalVersion normal) { this(normal, null, null); } @@ -269,6 +298,10 @@ public class Version implements Comparable { return result; } + public int compareWithBuildsTo(Version other) { + return BUILD_AWARE_ORDER.compare(this, other); + } + private int comparePreReleases(Version other) { int result = 0; if (preRelease != null && other.preRelease != null) { diff --git a/src/test/java/com/github/zafarkhaja/semver/VersionTest.java b/src/test/java/com/github/zafarkhaja/semver/VersionTest.java index 57997aa..a2688ba 100644 --- a/src/test/java/com/github/zafarkhaja/semver/VersionTest.java +++ b/src/test/java/com/github/zafarkhaja/semver/VersionTest.java @@ -292,6 +292,14 @@ public class VersionTest { Version incrementedBuild = version.incrementBuildMetadata(); assertNotSame(version, incrementedBuild); } + + @Test + public void shouldBeAbleToCompareWithoutIgnoringBuildMetadata() { + Version v1 = Version.valueOf("1.3.7-beta+build.1"); + Version v2 = Version.valueOf("1.3.7-beta+build.2"); + assertTrue(0 == v1.compareTo(v2)); + assertTrue(0 > v1.compareWithBuildsTo(v2)); + } } public static class EqualsMethodTest { @@ -404,4 +412,29 @@ public class VersionTest { assertEquals(Version.valueOf("1.0.0-alpha+build"), builder.build()); } } + + public static class BuildAwareOrderTest { + + @Test + public void shouldCorrectlyCompareAllVersionsWithBuildMetadata() { + String[] versions = { + "1.0.0-alpha", + "1.0.0-alpha.1", + "1.0.0-beta.2", + "1.0.0-beta.11", + "1.0.0-rc.1", + "1.0.0-rc.1+build.1", + "1.0.0", + "1.0.0+0.3.7", + "1.3.7+build", + "1.3.7+build.2.b8f12d7", + "1.3.7+build.11.e0f985a" + }; + for (int i = 1; i < versions.length; i++) { + Version v1 = Version.valueOf(versions[i-1]); + Version v2 = Version.valueOf(versions[i]); + assertTrue(0 > Version.BUILD_AWARE_ORDER.compare(v1, v2)); + } + } + } }