From 9aa8c4656088c14febb4c2af97d0cc312d6710b9 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 19 Apr 2017 15:09:30 +0200 Subject: [PATCH] Updated SemVerComparator to support pre-release versions. --- .../cryptomator/common/SemVerComparator.java | 45 +++++++++++++++++-- .../common/SemVerComparatorTest.java | 19 +++++--- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/SemVerComparator.java b/main/commons/src/main/java/org/cryptomator/common/SemVerComparator.java index 930e2e93d..e6975d1aa 100644 --- a/main/commons/src/main/java/org/cryptomator/common/SemVerComparator.java +++ b/main/commons/src/main/java/org/cryptomator/common/SemVerComparator.java @@ -12,12 +12,51 @@ import java.util.Comparator; import org.apache.commons.lang3.StringUtils; +/** + * Compares version strings according to SemVer 2.0.0. + */ public class SemVerComparator implements Comparator { + private static final char VERSION_SEP = '.'; // http://semver.org/spec/v2.0.0.html#spec-item-2 + private static final String PRE_RELEASE_SEP = "-"; // http://semver.org/spec/v2.0.0.html#spec-item-9 + private static final String BUILD_SEP = "+"; // http://semver.org/spec/v2.0.0.html#spec-item-10 + @Override public int compare(String version1, String version2) { - final String[] vComps1 = StringUtils.split(version1, '.'); - final String[] vComps2 = StringUtils.split(version2, '.'); + // "Build metadata SHOULD be ignored when determining version precedence. + // Thus two versions that differ only in the build metadata, have the same precedence." + String v1WithoutBuildMetadata = StringUtils.substringBefore(version1, BUILD_SEP); + String v2WithoutBuildMetadata = StringUtils.substringBefore(version2, BUILD_SEP); + + if (v1WithoutBuildMetadata.equals(v2WithoutBuildMetadata)) { + return 0; + } + + String v1MajorMinorPatch = StringUtils.substringBefore(v1WithoutBuildMetadata, PRE_RELEASE_SEP); + String v2MajorMinorPatch = StringUtils.substringBefore(v2WithoutBuildMetadata, PRE_RELEASE_SEP); + String v1PreReleaseVersion = StringUtils.substringAfter(v1WithoutBuildMetadata, PRE_RELEASE_SEP); + String v2PreReleaseVersion = StringUtils.substringAfter(v2WithoutBuildMetadata, PRE_RELEASE_SEP); + return compare(v1MajorMinorPatch, v1PreReleaseVersion, v2MajorMinorPatch, v2PreReleaseVersion); + } + + private int compare(String v1MajorMinorPatch, String v1PreReleaseVersion, String v2MajorMinorPatch, String v2PreReleaseVersion) { + int comparisonResult = compareNumericallyThenLexicographically(v1MajorMinorPatch, v2MajorMinorPatch); + if (comparisonResult == 0) { + if (v1PreReleaseVersion.isEmpty()) { + return 1; // 1.0.0 > 1.0.0-BETA + } else if (v2PreReleaseVersion.isEmpty()) { + return -1; // 1.0.0-BETA < 1.0.0 + } else { + return compareNumericallyThenLexicographically(v1PreReleaseVersion, v2PreReleaseVersion); + } + } else { + return comparisonResult; + } + } + + private int compareNumericallyThenLexicographically(String version1, String version2) { + final String[] vComps1 = StringUtils.split(version1, VERSION_SEP); + final String[] vComps2 = StringUtils.split(version2, VERSION_SEP); final int commonCompCount = Math.min(vComps1.length, vComps2.length); for (int i = 0; i < commonCompCount; i++) { @@ -35,7 +74,7 @@ public class SemVerComparator implements Comparator { } } - // all in common so far? longest version string wins: + // all in common so far? longest version string is considered the higher version: return vComps1.length - vComps2.length; } diff --git a/main/commons/src/test/java/org/cryptomator/common/SemVerComparatorTest.java b/main/commons/src/test/java/org/cryptomator/common/SemVerComparatorTest.java index 859eb9471..f9c44c0b2 100644 --- a/main/commons/src/test/java/org/cryptomator/common/SemVerComparatorTest.java +++ b/main/commons/src/test/java/org/cryptomator/common/SemVerComparatorTest.java @@ -10,7 +10,6 @@ package org.cryptomator.common; import java.util.Comparator; -import org.cryptomator.common.SemVerComparator; import org.junit.Assert; import org.junit.Test; @@ -22,8 +21,10 @@ public class SemVerComparatorTest { @Test public void compareEqualVersions() { - final int comparisonResult = semVerComparator.compare("1.23.4", "1.23.4"); - Assert.assertEquals(0, Integer.signum(comparisonResult)); + Assert.assertEquals(0, Integer.signum(semVerComparator.compare("1.23.4", "1.23.4"))); + Assert.assertEquals(0, Integer.signum(semVerComparator.compare("1.23.4-alpha", "1.23.4-alpha"))); + Assert.assertEquals(0, Integer.signum(semVerComparator.compare("1.23.4+20170101", "1.23.4+20171231"))); + Assert.assertEquals(0, Integer.signum(semVerComparator.compare("1.23.4-alpha+20170101", "1.23.4-alpha+20171231"))); } // newer versions in first argument @@ -33,7 +34,11 @@ public class SemVerComparatorTest { Assert.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.5", "1.23.4"))); Assert.assertEquals(1, Integer.signum(semVerComparator.compare("1.24.4", "1.23.4"))); Assert.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4", "1.23"))); - Assert.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4a", "1.23.4"))); + Assert.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4", "1.23.4-SNAPSHOT"))); + Assert.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4", "1.23.4-56.78"))); + Assert.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4-beta", "1.23.4-alpha"))); + Assert.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4-alpha.1", "1.23.4-alpha"))); + Assert.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4-56.79", "1.23.4-56.78"))); } // newer versions in second argument @@ -43,7 +48,11 @@ public class SemVerComparatorTest { Assert.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4", "1.23.5"))); Assert.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4", "1.24.4"))); Assert.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23", "1.23.4"))); - Assert.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4", "1.23.4a"))); + Assert.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4-SNAPSHOT", "1.23.4"))); + Assert.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4-56.78", "1.23.4"))); + Assert.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4-alpha", "1.23.4-beta"))); + Assert.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4-alpha", "1.23.4-alpha.1"))); + Assert.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4-56.78", "1.23.4-56.79"))); } }