diff --git a/core/src/main/scala/sbt/internal/librarymanagement/SemanticSelectorExtra.scala b/core/src/main/scala/sbt/internal/librarymanagement/SemanticSelectorExtra.scala index f3f28cf7a..8fafce2a0 100644 --- a/core/src/main/scala/sbt/internal/librarymanagement/SemanticSelectorExtra.scala +++ b/core/src/main/scala/sbt/internal/librarymanagement/SemanticSelectorExtra.scala @@ -148,7 +148,7 @@ private[librarymanagement] abstract class SemComparatorFunctions { (?:\.(\d+|[xX*]) (?:\.(\d+|[xX*]))? )? - )((?:-\w+)*)$ + )((?:-\w+(?:\.\w+)*)*)$ """.r protected def parse(comparator: String): SemComparator = { comparator match { diff --git a/core/src/main/scala/sbt/internal/librarymanagement/cross/CrossVersionUtil.scala b/core/src/main/scala/sbt/internal/librarymanagement/cross/CrossVersionUtil.scala index 15e7bb9bb..1bb3d8213 100644 --- a/core/src/main/scala/sbt/internal/librarymanagement/cross/CrossVersionUtil.scala +++ b/core/src/main/scala/sbt/internal/librarymanagement/cross/CrossVersionUtil.scala @@ -22,12 +22,13 @@ object CrossVersionUtil { private val longPattern = """\d{1,19}""" private val basicVersion = raw"""($longPattern)\.($longPattern)\.($longPattern)""" + private val tagPattern = raw"""(?:\w+(?:\.\w+)*)""" private val ReleaseV = raw"""$basicVersion(-\d+)?""".r - private val BinCompatV = raw"""$basicVersion(-\w+)?-bin(-.*)?""".r + private[sbt] val BinCompatV = raw"""$basicVersion(-$tagPattern)?-bin(-.*)?""".r private val CandidateV = raw"""$basicVersion(-RC\d+)""".r - private val MilestonV = raw"""$basicVersion(-M\d+)""".r - private val NonReleaseV_n = raw"""$basicVersion([-\w]*)""".r // 0-n word suffixes, with leading dashes - private val NonReleaseV_1 = raw"""$basicVersion(-\w+)""".r // 1 word suffix, after a dash + private val MilestonV = raw"""$basicVersion(-M$tagPattern)""".r + private val NonReleaseV_n = raw"""$basicVersion((?:-$tagPattern)*)""".r // 0-n word suffixes, with leading dashes + private val NonReleaseV_1 = raw"""$basicVersion(-$tagPattern)""".r // 1 word suffix, after a dash private[sbt] val PartialVersion = raw"""($longPattern)\.($longPattern)(?:\..+)?""".r private[sbt] def isSbtApiCompatible(v: String): Boolean = sbtApiVersion(v).isDefined diff --git a/core/src/main/scala/sbt/librarymanagement/CrossVersionExtra.scala b/core/src/main/scala/sbt/librarymanagement/CrossVersionExtra.scala index a37a52d7c..9de8605ea 100644 --- a/core/src/main/scala/sbt/librarymanagement/CrossVersionExtra.scala +++ b/core/src/main/scala/sbt/librarymanagement/CrossVersionExtra.scala @@ -102,7 +102,7 @@ private[librarymanagement] abstract class CrossVersionFunctions { } private[sbt] def patchFun(fullVersion: String): String = { - val BinCompatV = """(\d+)\.(\d+)\.(\d+)(-\w+)??-bin(-.*)?""".r + import sbt.internal.librarymanagement.cross.CrossVersionUtil.BinCompatV fullVersion match { case BinCompatV(x, y, z, w, _) => s"""$x.$y.$z${if (w == null) "" else w}""" case other => other diff --git a/core/src/main/scala/sbt/librarymanagement/VersionNumber.scala b/core/src/main/scala/sbt/librarymanagement/VersionNumber.scala index 90897351d..8ce15c72d 100644 --- a/core/src/main/scala/sbt/librarymanagement/VersionNumber.scala +++ b/core/src/main/scala/sbt/librarymanagement/VersionNumber.scala @@ -66,7 +66,7 @@ object VersionNumber { def splitDash(s: String) = splitOn(s, '-') def splitPlus(s: String) = splitOn(s, '+') map ("+" + _) - val TaggedVersion = """(\d{1,14})([\.\d{1,14}]*)((?:-[\w\.]+)*)((?:\+.+)*)""".r + val TaggedVersion = """(\d{1,14})([\.\d{1,14}]*)((?:-\w+(?:\.\w+)*)*)((?:\+.+)*)""".r val NonSpaceString = """(\S+)""".r s match { diff --git a/core/src/test/scala/sbt/librarymanagement/CrossVersionTest.scala b/core/src/test/scala/sbt/librarymanagement/CrossVersionTest.scala index 05e849520..454bb5403 100644 --- a/core/src/test/scala/sbt/librarymanagement/CrossVersionTest.scala +++ b/core/src/test/scala/sbt/librarymanagement/CrossVersionTest.scala @@ -138,6 +138,9 @@ class CrossVersionTest extends UnitSpec { it should "for 1.3.0-SNAPSHOT return 1.0" in { binarySbtVersion("1.3.0-SNAPSHOT") shouldBe "1.0" } + it should "for 1.3.0-A1-B1.1 return 1.0" in { + binarySbtVersion("1.3.0-A1-B1.1") shouldBe "1.0" + } it should "for 1.10.0 return 1.0" in { binarySbtVersion("1.10.0") shouldBe "1.0" } @@ -216,6 +219,9 @@ class CrossVersionTest extends UnitSpec { it should "for 3.0.0-M3-bin-20201215-cbe50b3-NIGHTLY return 3.0.0-M3" in { binaryScalaVersion("3.0.0-M3-bin-20201215-cbe50b3-NIGHTLY") shouldBe "3.0.0-M3" } + it should "for 3.0.0-M3.5-bin-20201215-cbe50b3-NIGHTLY return 3.0.0-M3" in { + binaryScalaVersion("3.0.0-M3.5-bin-20201215-cbe50b3-NIGHTLY") shouldBe "3.0.0-M3.5" + } it should "for 3.0.0-RC1 return 3.0.0-RC1" in { binaryScalaVersion("3.0.0-RC1") shouldBe "3.0.0-RC1" } @@ -268,6 +274,9 @@ class CrossVersionTest extends UnitSpec { it should "for 2.11.8-RC1-bin-extra return 2.11.8-RC1" in { patchVersion("2.11.8-RC1-bin-extra") shouldBe Some("artefact_2.11.8-RC1") } + it should "for 2.11.8-X1.5-bin-extra return 2.11.8-X1.5" in { + patchVersion("2.11.8-X1.5-bin-extra") shouldBe Some("artefact_2.11.8-X1.5") + } private def constantVersion(value: String) = CrossVersion(CrossVersion.constant(value), "dummy1", "dummy2") map (fn => fn("artefact")) diff --git a/core/src/test/scala/sbt/librarymanagement/SemanticSelectorSpec.scala b/core/src/test/scala/sbt/librarymanagement/SemanticSelectorSpec.scala index 411554260..cce9b4ff1 100644 --- a/core/src/test/scala/sbt/librarymanagement/SemanticSelectorSpec.scala +++ b/core/src/test/scala/sbt/librarymanagement/SemanticSelectorSpec.scala @@ -75,6 +75,7 @@ class SemanticSelectorSpec extends AnyFreeSpec with Matchers { semsel(">=1.2.3") { sel => assertMatches(sel, "1.2.4-beta") + assertMatches(sel, "1.2.4-beta.1") assertMatches(sel, "1.2.3") assertMatches(sel, "1.3") assertMatches(sel, "2") @@ -306,6 +307,21 @@ class SemanticSelectorSpec extends AnyFreeSpec with Matchers { assertNotMatches(sel, "1.2.2") } + semsel(">=1.2.3-beta.5") { sel => + assertMatches(sel, "1.3-alpha") + assertMatches(sel, "1.2.3") + assertMatches(sel, "1.2.3-beta.5") + assertMatches(sel, "1.2.3-beta.6-3") + assertMatches(sel, "1.2.3-beta.7") + assertMatches(sel, "1.2.3-beta.gamma") + assertMatches(sel, "1.2.4") + assertMatches(sel, "1.3") + assertNotMatches(sel, "1.2.3-alpha-3") + assertNotMatches(sel, "1.2.3-beta-1") + assertNotMatches(sel, "1.2.3-beta") + assertNotMatches(sel, "1.2.2") + } + Seq( // invalid operator "~1.2.3", @@ -339,7 +355,6 @@ class SemanticSelectorSpec extends AnyFreeSpec with Matchers { "1.0.0 - 2.0.0 || - 2.0.0", "1.0.0- 2.0.0", "1.0.0 -2.0.0", - "1.0.0-2.0.0", "-", // minor and patch versions are required for pre-release version "1.2-alpha-beta",