diff --git a/ivy/src/test/scala/CrossVersionTest.scala b/ivy/src/test/scala/CrossVersionTest.scala index 0e0e7ed9d..984e55b85 100644 --- a/ivy/src/test/scala/CrossVersionTest.scala +++ b/ivy/src/test/scala/CrossVersionTest.scala @@ -118,6 +118,9 @@ object CrossVersionTest extends Specification { "return binary Scala version for 2.10.1 as 2.10" in { CrossVersion.binaryScalaVersion("2.10.1") must_== "2.10" } + "return binary Scala version for 2.20170314093845.0-87654321 as 2.20170314093845.0-87654321" in { + CrossVersion.binaryScalaVersion("2.20170314093845.0-87654321") must_== "2.20170314093845.0-87654321" + } "return patch Scala version for 2.11.8 as 2.11.8" in { CrossVersion(CrossVersion.patch, "2.11.8", "dummy").map(_("artefact")) must_== Some("artefact_2.11.8") diff --git a/notes/0.13.14.markdown b/notes/0.13.14.markdown index bddaeed3a..2d5df5bed 100644 --- a/notes/0.13.14.markdown +++ b/notes/0.13.14.markdown @@ -26,6 +26,7 @@ - Fixes script mode ignoring quotation. [#2551][2551] by [@ekrich][@ekrich] - Fixes IllegalStateException that Ivy gets into sometimes. [#2827][2827]/[#2015][2015] by [@eed3si9n][@eed3si9n] - Fixes null sourceFile causing NPE. [#2766][2766] by [@avdv][@avdv] +- Fixes version parsing in validation. [#3011][3011] by [@eed3si9n][@eed3si9n] ### Maven version range improvement @@ -84,6 +85,7 @@ Special thanks to the contributors for making this release a success. According [2902]: https://github.com/sbt/sbt/pull/2902 [2993]: https://github.com/sbt/sbt/pull/2993 [2943]: https://github.com/sbt/sbt/pull/2943 + [3011]: https://github.com/sbt/sbt/issues/3011 [@eed3si9n]: https://github.com/eed3si9n [@dwijnand]: https://github.com/dwijnand [@Duhemm]: https://github.com/Duhemm diff --git a/util/cross/src/main/input_sources/CrossVersionUtil.scala b/util/cross/src/main/input_sources/CrossVersionUtil.scala index 6a63c9139..5bf0359d4 100644 --- a/util/cross/src/main/input_sources/CrossVersionUtil.scala +++ b/util/cross/src/main/input_sources/CrossVersionUtil.scala @@ -15,6 +15,9 @@ object CrossVersionUtil def isDisabled(s: String): Boolean = (s == falseString) || (s == noneString) || (s == disabledString) def isBinary(s: String): Boolean = (s == binaryString) + private lazy val intPattern = """\d{1,10}""" + private lazy val basicVersion = """(""" + intPattern + """)\.(""" + intPattern + """)\.(""" + intPattern + """)""" + private[${{cross.package0}}] def isSbtApiCompatible(v: String): Boolean = sbtApiVersion(v).isDefined /** Returns sbt binary interface x.y API compatible with the given version string v. * RCs for x.y.0 are considered API compatible. @@ -22,9 +25,9 @@ object CrossVersionUtil */ private[${{cross.package0}}] def sbtApiVersion(v: String): Option[(Int, Int)] = { - val ReleaseV = """(\d+)\.(\d+)\.(\d+)(-\d+)?""".r - val CandidateV = """(\d+)\.(\d+)\.(\d+)(-RC\d+)""".r - val NonReleaseV = """(\d+)\.(\d+)\.(\d+)([-\w+]*)""".r + val ReleaseV = (basicVersion + """(-\d+)?""").r + val CandidateV = (basicVersion + """(-RC\d+)""").r + val NonReleaseV = (basicVersion + """([-\w+]*)""").r v match { case ReleaseV(x, y, z, ht) => Some((x.toInt, y.toInt)) case CandidateV(x, y, z, ht) => Some((x.toInt, y.toInt)) @@ -38,9 +41,9 @@ object CrossVersionUtil */ private[${{cross.package0}}] def scalaApiVersion(v: String): Option[(Int, Int)] = { - val ReleaseV = """(\d+)\.(\d+)\.(\d+)(-\d+)?""".r - val BinCompatV = """(\d+)\.(\d+)\.(\d+)-bin(-.*)?""".r - val NonReleaseV = """(\d+)\.(\d+)\.(\d+)(-\w+)""".r + val ReleaseV = (basicVersion + """(-\d+)?""").r + val BinCompatV = (basicVersion + """-bin(-.*)?""").r + val NonReleaseV = (basicVersion + """(-\w+)""").r v match { case ReleaseV(x, y, z, ht) => Some((x.toInt, y.toInt)) case BinCompatV(x, y, z, ht) => Some((x.toInt, y.toInt)) @@ -48,8 +51,8 @@ object CrossVersionUtil case _ => None } } - private[${{cross.package0}}] val PartialVersion = """(\d+)\.(\d+)(?:\..+)?""".r - private[${{cross.package0}}] def partialVersion(s: String): Option[(Int,Int)] = + private[${{cross.package0}}] val PartialVersion = ("""(""" + intPattern + """)\.(""" + intPattern + """)(?:\..+)?""").r + private[${{cross.package0}}] def partialVersion(s: String): Option[(Int, Int)] = s match { case PartialVersion(major, minor) => Some((major.toInt, minor.toInt)) case _ => None @@ -59,7 +62,7 @@ object CrossVersionUtil private[${{cross.package0}}] def binaryVersion(full: String, cutoff: String): String = binaryVersionWithApi(full, cutoff)(scalaApiVersion) private[this] def isNewer(major: Int, minor: Int, minMajor: Int, minMinor: Int): Boolean = major > minMajor || (major == minMajor && minor >= minMinor) - private[this] def binaryVersionWithApi(full: String, cutoff: String)(apiVersion: String => Option[(Int,Int)]): String = + private[this] def binaryVersionWithApi(full: String, cutoff: String)(apiVersion: String => Option[(Int, Int)]): String = { def sub(major: Int, minor: Int) = major + "." + minor (apiVersion(full), partialVersion(cutoff)) match {