From 8973fce1fabca1e50cecc4feda5ddde1f864e2a2 Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Sun, 26 Jun 2022 12:31:22 +0200 Subject: [PATCH] More flexible Scala version switch By using SemanticSelector instead of custom globbing. Follow-up on https://github.com/sbt/sbt/pull/6894, fixes https://github.com/sbt/sbt/issues/6934 --- main/src/main/scala/sbt/Cross.scala | 28 ++++++++----------- main/src/test/scala/sbt/CrossSpec.scala | 20 ------------- .../sbt-test/actions/cross-multiproject/test | 2 +- 3 files changed, 12 insertions(+), 38 deletions(-) delete mode 100644 main/src/test/scala/sbt/CrossSpec.scala diff --git a/main/src/main/scala/sbt/Cross.scala b/main/src/main/scala/sbt/Cross.scala index 9966c5eb9..73b4cadec 100644 --- a/main/src/main/scala/sbt/Cross.scala +++ b/main/src/main/scala/sbt/Cross.scala @@ -8,7 +8,6 @@ package sbt import java.io.File -import java.util.regex.Pattern import sbt.Def.{ ScopedKey, Setting } import sbt.Keys._ import sbt.SlashSyntax0._ @@ -19,7 +18,7 @@ import sbt.internal.util.AttributeKey import sbt.internal.util.complete.DefaultParsers._ import sbt.internal.util.complete.{ DefaultParsers, Parser } import sbt.io.IO -import sbt.librarymanagement.CrossVersion +import sbt.librarymanagement.{ CrossVersion, SemanticSelector, VersionNumber } /** * Cross implements the Scala cross building commands: @@ -327,10 +326,11 @@ object Cross { } ++ structure.units.keys .map(BuildRef.apply) .map(proj => (proj, Some(version), crossVersions(extracted, proj))) - } else if (version.contains('*')) { + } else if (isSelector(version)) { + val selector = SemanticSelector(version) projectScalaVersions.map { case (project, scalaVersions) => - globFilter(version, scalaVersions) match { + scalaVersions.filter(v => selector.matches(VersionNumber(v))) match { case Nil => (project, None, scalaVersions) case Seq(version) => (project, Some(version), scalaVersions) case multiple => @@ -370,19 +370,13 @@ object Cross { (setScalaVersionsForProjects(instance, included, state, extracted), included.map(_._1)) } - def globFilter(pattern: String, candidates: Seq[String]): Seq[String] = { - def createGlobRegex(remainingPattern: String): String = - remainingPattern.indexOf("*") match { - case -1 => Pattern.quote(remainingPattern) - case n => - val chunk = Pattern.quote(remainingPattern.substring(0, n)) + ".*" - if (remainingPattern.length > n) - chunk + createGlobRegex(remainingPattern.substring(n + 1)) - else chunk - } - val compiledPattern = Pattern.compile(createGlobRegex(pattern)) - candidates.filter(compiledPattern.matcher(_).matches()) - } + // determine whether this is a 'specific' version or a selector + // to be passed to SemanticSelector + private def isSelector(version: String): Boolean = + version.contains('*') || version.contains('x') || version.contains('X') || version.contains(' ') || + version.contains('<') || version.contains('>') || version.contains('|') || version.contains( + '=' + ) private def setScalaVersionsForProjects( instance: Option[(File, ScalaInstance)], diff --git a/main/src/test/scala/sbt/CrossSpec.scala b/main/src/test/scala/sbt/CrossSpec.scala deleted file mode 100644 index 40673d548..000000000 --- a/main/src/test/scala/sbt/CrossSpec.scala +++ /dev/null @@ -1,20 +0,0 @@ -/* - * sbt - * Copyright 2011 - 2018, Lightbend, Inc. - * Copyright 2008 - 2010, Mark Harrah - * Licensed under Apache License 2.0 (see LICENSE) - */ - -package sbt - -object CrossSpec extends verify.BasicTestSuite { - import Cross._ - - test("glob filter should work as expected") { - assert(globFilter("2.13.*", Seq("2.12.8", "2.13.16", "3.0.1")) == Seq("2.13.16")) - assert(globFilter("3.*", Seq("2.12.8", "2.13.16", "3.0.1")) == Seq("3.0.1")) - assert(globFilter("3.*", Seq("3.0.1", "30.1")) == Seq("3.0.1")) - assert(globFilter("2.*", Seq("2.12.8", "2.13.16", "3.0.1")) == Seq("2.12.8", "2.13.16")) - assert(globFilter("4.*", Seq("2.12.8", "2.13.16", "3.0.1")) == Nil) - } -} diff --git a/sbt-app/src/sbt-test/actions/cross-multiproject/test b/sbt-app/src/sbt-test/actions/cross-multiproject/test index baf4db9b8..b464e9cb3 100644 --- a/sbt-app/src/sbt-test/actions/cross-multiproject/test +++ b/sbt-app/src/sbt-test/actions/cross-multiproject/test @@ -52,7 +52,7 @@ $ exists sbt-foo/target/scala-2.12 # test wildcard switching (2.13) > clean -> ++ 2.13.* -v compile +> ++ 2.13.x -v compile $ exists lib/target/scala-2.13 -$ exists lib/target/scala-2.12 # -$ exists sbt-foo/target/scala-2.12