diff --git a/ivy/src/main/scala/sbt/Configuration.scala b/ivy/src/main/scala/sbt/Configuration.scala index d2307b89d..f502b7d10 100644 --- a/ivy/src/main/scala/sbt/Configuration.scala +++ b/ivy/src/main/scala/sbt/Configuration.scala @@ -51,6 +51,15 @@ object Configurations { private[sbt] def DefaultConfiguration(mavenStyle: Boolean) = if (mavenStyle) DefaultMavenConfiguration else DefaultIvyConfiguration private[sbt] def defaultConfiguration(mavenStyle: Boolean) = if (mavenStyle) Configurations.Compile else Configurations.Default private[sbt] def removeDuplicates(configs: Iterable[Configuration]) = Set(scala.collection.mutable.Map(configs.map(config => (config.name, config)).toSeq: _*).values.toList: _*) + + /** Returns true if the configuration should be under the influence of scalaVersion. */ + private[sbt] def underScalaVersion(c: Configuration): Boolean = + c match { + case Default | Compile | IntegrationTest | Provided | Runtime | Test | Optional | + CompilerPlugin | CompileInternal | RuntimeInternal | TestInternal => true + case config => + config.extendsConfigs exists underScalaVersion + } } /** Represents an Ivy configuration. */ final case class Configuration(name: String, description: String, isPublic: Boolean, extendsConfigs: List[Configuration], transitive: Boolean) { diff --git a/ivy/src/main/scala/sbt/Ivy.scala b/ivy/src/main/scala/sbt/Ivy.scala index ef9b695e9..fdf3c6b88 100644 --- a/ivy/src/main/scala/sbt/Ivy.scala +++ b/ivy/src/main/scala/sbt/Ivy.scala @@ -174,7 +174,21 @@ final class IvySbt(val configuration: IvyConfiguration) { case pc: PomConfiguration => configurePom(pc) case ifc: IvyFileConfiguration => configureIvyFile(ifc) } - moduleSettings.ivyScala.foreach(IvyScala.checkModule(baseModule, baseConfiguration, configuration.log)) + + val configs = + moduleSettings match { + case ic: InlineConfiguration => ic.configurations + case ic: InlineConfigurationWithExcludes => ic.configurations + case ec: EmptyConfiguration => Nil + case pc: PomConfiguration => Configurations.default ++ Configurations.defaultInternal + case ifc: IvyFileConfiguration => Configurations.default ++ Configurations.defaultInternal + } + moduleSettings.ivyScala match { + case Some(is) => + val svc = configs.toVector filter Configurations.underScalaVersion map { _.name } + IvyScala.checkModule(baseModule, baseConfiguration, svc, configuration.log)(is) + case _ => // do nothing + } IvySbt.addExtraNamespace(baseModule) (baseModule, baseConfiguration) } diff --git a/ivy/src/main/scala/sbt/IvyScala.scala b/ivy/src/main/scala/sbt/IvyScala.scala index 8bf8cb780..19bb50207 100644 --- a/ivy/src/main/scala/sbt/IvyScala.scala +++ b/ivy/src/main/scala/sbt/IvyScala.scala @@ -49,24 +49,28 @@ final case class IvyScala(scalaFullVersion: String, scalaBinaryVersion: String, private object IvyScala { /** Performs checks/adds filters on Scala dependencies (if enabled in IvyScala). */ - def checkModule(module: DefaultModuleDescriptor, conf: String, log: Logger)(check: IvyScala): Unit = { + def checkModule(module: DefaultModuleDescriptor, conf: String, scalaVersionConfigs: Vector[String], log: Logger)(check: IvyScala): Unit = { if (check.checkExplicit) checkDependencies(module, check.scalaOrganization, check.scalaBinaryVersion, check.configurations, log) if (check.filterImplicit) excludeScalaJars(module, check.configurations) if (check.overrideScalaVersion) - overrideScalaVersion(module, check.scalaOrganization, check.scalaFullVersion) + overrideScalaVersion(module, check.scalaOrganization, check.scalaFullVersion, scalaVersionConfigs) } - class OverrideScalaMediator(scalaOrganization: String, scalaVersion: String) extends DependencyDescriptorMediator { + class OverrideScalaMediator(scalaOrganization: String, scalaVersion: String, scalaVersionConfigs0: Vector[String]) extends DependencyDescriptorMediator { + private[this] val scalaVersionConfigs = scalaVersionConfigs0.toSet def mediate(dd: DependencyDescriptor): DependencyDescriptor = { + // Mediate only for the dependencies in scalaVersion configurations. https://github.com/sbt/sbt/issues/2786 + def configQualifies: Boolean = + (dd.getModuleConfigurations exists { scalaVersionConfigs }) val transformer = new NamespaceTransformer { def transform(mrid: ModuleRevisionId): ModuleRevisionId = { if (mrid == null) mrid else mrid.getName match { - case name @ (CompilerID | LibraryID | ReflectID | ActorsID | ScalapID) => + case name @ (CompilerID | LibraryID | ReflectID | ActorsID | ScalapID) if configQualifies => ModuleRevisionId.newInstance(scalaOrganization, name, mrid.getBranch, scalaVersion, mrid.getQualifiedExtraAttributes) case _ => mrid } @@ -79,8 +83,8 @@ private object IvyScala { } } - def overrideScalaVersion(module: DefaultModuleDescriptor, organization: String, version: String): Unit = { - val mediator = new OverrideScalaMediator(organization, version) + def overrideScalaVersion(module: DefaultModuleDescriptor, organization: String, version: String, scalaVersionConfigs: Vector[String]): Unit = { + val mediator = new OverrideScalaMediator(organization, version, scalaVersionConfigs) module.addDependencyDescriptorMediator(new ModuleId(Organization, "*"), ExactPatternMatcher.INSTANCE, mediator) if (organization != Organization) module.addDependencyDescriptorMediator(new ModuleId(organization, "*"), ExactPatternMatcher.INSTANCE, mediator) diff --git a/ivy/src/test/scala/ScalaOverrideTest.scala b/ivy/src/test/scala/ScalaOverrideTest.scala index 9165487bd..9daa3832d 100644 --- a/ivy/src/test/scala/ScalaOverrideTest.scala +++ b/ivy/src/test/scala/ScalaOverrideTest.scala @@ -14,10 +14,12 @@ object ScalaOverrideTest extends Specification { val OtherOrgID = "other.org" def check(org0: String, version0: String)(org1: String, name1: String, version1: String) = { - val osm = new OverrideScalaMediator(org0, version0) + val scalaConfigs = Configurations.default.toVector filter { Configurations.underScalaVersion } map { _.name } + val osm = new OverrideScalaMediator(org0, version0, scalaConfigs) val mrid = ModuleRevisionId.newInstance(org1, name1, version1) val dd = new DefaultDependencyDescriptor(mrid, false) + dd.addDependencyConfiguration("compile", "compile") val res = osm.mediate(dd) res.getDependencyRevisionId must_== ModuleRevisionId.newInstance(org0, name1, version0) diff --git a/notes/0.13.14/mediator_fix.md b/notes/0.13.14/mediator_fix.md new file mode 100644 index 000000000..ad0502a34 --- /dev/null +++ b/notes/0.13.14/mediator_fix.md @@ -0,0 +1,9 @@ +### Bug fixes + +- Fixes a regression in sbt 0.13.12 that was misfiring Scala version enforcement when configuration does not extend `Compile`. [#2827][2827]/[#2786][2786] by [@eed3si9n][@eed3si9n] + + [2786]: https://github.com/sbt/sbt/issues/2786 + [2827]: https://github.com/sbt/sbt/pull/2827 + [@eed3si9n]: https://github.com/eed3si9n + [@dwijnand]: https://github.com/dwijnand + [@Duhemm]: https://github.com/Duhemm diff --git a/sbt/src/sbt-test/dependency-management/scala-organization/build.sbt b/sbt/src/sbt-test/dependency-management/scala-organization/build.sbt index 217b3f4d7..2ee2d59da 100644 --- a/sbt/src/sbt-test/dependency-management/scala-organization/build.sbt +++ b/sbt/src/sbt-test/dependency-management/scala-organization/build.sbt @@ -49,6 +49,5 @@ checkDependencies := { m <- c.modules if !m.evicted } yield m.module.copy(extraAttributes = Map.empty)).toSet - assert(resolved == expected) }