mirror of https://github.com/sbt/sbt.git
Merge pull request #44 from milessabin/topic/scala-override
Override scala organization and version transitively at the Ivy level
This commit is contained in:
commit
d2e6133704
|
|
@ -9,6 +9,7 @@ import scala.collection.mutable.HashSet
|
|||
import org.apache.ivy.core.module.descriptor._
|
||||
import org.apache.ivy.core.module.id.{ ArtifactId, ModuleId, ModuleRevisionId }
|
||||
import org.apache.ivy.plugins.matcher.ExactPatternMatcher
|
||||
import org.apache.ivy.plugins.namespace.NamespaceTransformer
|
||||
import sbt.util.Logger
|
||||
|
||||
object ScalaArtifacts {
|
||||
|
|
@ -16,6 +17,8 @@ object ScalaArtifacts {
|
|||
val LibraryID = "scala-library"
|
||||
val CompilerID = "scala-compiler"
|
||||
val ReflectID = "scala-reflect"
|
||||
val ActorsID = "scala-actors"
|
||||
val ScalapID = "scalap"
|
||||
val DottyIDPrefix = "dotty"
|
||||
|
||||
def dottyID(binaryVersion: String): String = s"${DottyIDPrefix}_${binaryVersion}"
|
||||
|
|
@ -47,17 +50,41 @@ private[sbt] object IvyScala {
|
|||
/** Performs checks/adds filters on Scala dependencies (if enabled in IvyScala). */
|
||||
def checkModule(module: DefaultModuleDescriptor, conf: String, log: Logger)(check: IvyScala): Unit = {
|
||||
if (check.checkExplicit)
|
||||
checkDependencies(module, check.scalaBinaryVersion, check.configurations, log)
|
||||
checkDependencies(module, check.scalaOrganization, check.scalaBinaryVersion, check.configurations, log)
|
||||
if (check.filterImplicit)
|
||||
excludeScalaJars(module, check.configurations)
|
||||
if (check.overrideScalaVersion)
|
||||
overrideScalaVersion(module, check.scalaFullVersion)
|
||||
overrideScalaVersion(module, check.scalaOrganization, check.scalaFullVersion)
|
||||
}
|
||||
def overrideScalaVersion(module: DefaultModuleDescriptor, version: String): Unit = {
|
||||
overrideVersion(module, Organization, LibraryID, version)
|
||||
overrideVersion(module, Organization, CompilerID, version)
|
||||
overrideVersion(module, Organization, ReflectID, version)
|
||||
|
||||
class OverrideScalaMediator(scalaOrganization: String, scalaVersion: String) extends DependencyDescriptorMediator {
|
||||
def mediate(dd: DependencyDescriptor): DependencyDescriptor = {
|
||||
val transformer =
|
||||
new NamespaceTransformer {
|
||||
def transform(mrid: ModuleRevisionId): ModuleRevisionId = {
|
||||
if (mrid == null) mrid
|
||||
else
|
||||
mrid.getName match {
|
||||
case name @ (CompilerID | LibraryID | ReflectID | ActorsID | ScalapID) =>
|
||||
ModuleRevisionId.newInstance(scalaOrganization, name, mrid.getBranch, scalaVersion, mrid.getQualifiedExtraAttributes)
|
||||
case _ => mrid
|
||||
}
|
||||
}
|
||||
|
||||
def isIdentity: Boolean = false
|
||||
}
|
||||
|
||||
DefaultDependencyDescriptor.transformInstance(dd, transformer, false)
|
||||
}
|
||||
}
|
||||
|
||||
def overrideScalaVersion(module: DefaultModuleDescriptor, organization: String, version: String): Unit = {
|
||||
val mediator = new OverrideScalaMediator(organization, version)
|
||||
module.addDependencyDescriptorMediator(new ModuleId(Organization, "*"), ExactPatternMatcher.INSTANCE, mediator)
|
||||
if (organization != Organization)
|
||||
module.addDependencyDescriptorMediator(new ModuleId(organization, "*"), ExactPatternMatcher.INSTANCE, mediator)
|
||||
}
|
||||
|
||||
def overrideVersion(module: DefaultModuleDescriptor, org: String, name: String, version: String): Unit = {
|
||||
val id = new ModuleId(org, name)
|
||||
val over = new OverrideDependencyDescriptorMediator(null, version)
|
||||
|
|
@ -68,13 +95,13 @@ private[sbt] object IvyScala {
|
|||
* Checks the immediate dependencies of module for dependencies on scala jars and verifies that the version on the
|
||||
* dependencies matches scalaVersion.
|
||||
*/
|
||||
private def checkDependencies(module: ModuleDescriptor, scalaBinaryVersion: String, configurations: Iterable[Configuration], log: Logger): Unit = {
|
||||
private def checkDependencies(module: ModuleDescriptor, scalaOrganization: String, scalaBinaryVersion: String, configurations: Iterable[Configuration], log: Logger): Unit = {
|
||||
val configSet = if (configurations.isEmpty) (c: String) => true else configurationSet(configurations)
|
||||
def binaryScalaWarning(dep: DependencyDescriptor): Option[String] =
|
||||
{
|
||||
val id = dep.getDependencyRevisionId
|
||||
val depBinaryVersion = CrossVersion.binaryScalaVersion(id.getRevision)
|
||||
def isScalaLangOrg = id.getOrganisation == Organization
|
||||
def isScalaLangOrg = id.getOrganisation == scalaOrganization
|
||||
def isNotScalaActorsMigration = !(id.getName startsWith "scala-actors-migration") // Exception to the rule: sbt/sbt#1818
|
||||
def isNotScalaPickling = !(id.getName startsWith "scala-pickling") // Exception to the rule: sbt/sbt#1899
|
||||
def hasBinVerMismatch = depBinaryVersion != scalaBinaryVersion
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ trait BaseIvySpecification extends UnitSpec {
|
|||
|
||||
def configurations = Seq(Compile, Test, Runtime)
|
||||
def module(moduleId: ModuleID, deps: Seq[ModuleID], scalaFullVersion: Option[String],
|
||||
uo: UpdateOptions = UpdateOptions()): IvySbt#Module = {
|
||||
uo: UpdateOptions = UpdateOptions(), overrideScalaVersion: Boolean = true): IvySbt#Module = {
|
||||
val ivyScala = scalaFullVersion map { fv =>
|
||||
new IvyScala(
|
||||
scalaFullVersion = fv,
|
||||
|
|
@ -28,7 +28,7 @@ trait BaseIvySpecification extends UnitSpec {
|
|||
configurations = Nil,
|
||||
checkExplicit = true,
|
||||
filterImplicit = false,
|
||||
overrideScalaVersion = false
|
||||
overrideScalaVersion = overrideScalaVersion
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,12 +5,16 @@ import sbt.internal.librarymanagement.BaseIvySpecification
|
|||
class EvictionWarningSpec extends BaseIvySpecification {
|
||||
// This is a specification to check the eviction warnings
|
||||
|
||||
"""Eviction of scala-library whose scalaVersion
|
||||
"""Eviction of non-overridden scala-library whose scalaVersion
|
||||
""" should "be detected" in scalaVersionWarn1()
|
||||
it should "not be detected if it's diabled" in scalaVersionWarn2()
|
||||
it should "not be detected if it's disabled" in scalaVersionWarn2()
|
||||
it should "print out message about the eviction" in scalaVersionWarn3()
|
||||
it should "print out message about the eviction with callers" in scalaVersionWarn4()
|
||||
|
||||
"""Non-eviction of overridden scala-library whose scalaVersion
|
||||
""" should "not be detected if it's enabled" in scalaVersionWarn5()
|
||||
it should "not be detected if it's disabled" in scalaVersionWarn6()
|
||||
|
||||
"""Including two (suspect) binary incompatible Java libraries to direct dependencies
|
||||
""" should "be detected as eviction" in javaLibWarn1()
|
||||
it should "not be detected if it's disabled" in javaLibWarn2()
|
||||
|
|
@ -61,19 +65,19 @@ class EvictionWarningSpec extends BaseIvySpecification {
|
|||
def scalaVersionDeps = Seq(scala2102, akkaActor230)
|
||||
|
||||
def scalaVersionWarn1() = {
|
||||
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"))
|
||||
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
|
||||
val report = ivyUpdate(m)
|
||||
EvictionWarning(m, defaultOptions, report, log).scalaEvictions should have size (1)
|
||||
}
|
||||
|
||||
def scalaVersionWarn2() = {
|
||||
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"))
|
||||
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
|
||||
val report = ivyUpdate(m)
|
||||
EvictionWarning(m, defaultOptions.withWarnScalaVersionEviction(false), report, log).scalaEvictions should have size (0)
|
||||
}
|
||||
|
||||
def scalaVersionWarn3() = {
|
||||
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"))
|
||||
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
|
||||
val report = ivyUpdate(m)
|
||||
EvictionWarning(m, defaultOptions, report, log).lines shouldBe
|
||||
List(
|
||||
|
|
@ -86,7 +90,7 @@ class EvictionWarningSpec extends BaseIvySpecification {
|
|||
}
|
||||
|
||||
def scalaVersionWarn4() = {
|
||||
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"))
|
||||
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
|
||||
val report = ivyUpdate(m)
|
||||
EvictionWarning(m, defaultOptions.withShowCallers(true), report, log).lines shouldBe
|
||||
List(
|
||||
|
|
@ -97,6 +101,18 @@ class EvictionWarningSpec extends BaseIvySpecification {
|
|||
)
|
||||
}
|
||||
|
||||
def scalaVersionWarn5() = {
|
||||
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"))
|
||||
val report = ivyUpdate(m)
|
||||
EvictionWarning(m, defaultOptions, report, log).scalaEvictions should have size (0)
|
||||
}
|
||||
|
||||
def scalaVersionWarn6() = {
|
||||
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"))
|
||||
val report = ivyUpdate(m)
|
||||
EvictionWarning(m, defaultOptions.withWarnScalaVersionEviction(false), report, log).scalaEvictions should have size (0)
|
||||
}
|
||||
|
||||
def javaLibDirectDeps = Seq(commonsIo14, commonsIo24)
|
||||
|
||||
def javaLibWarn1() = {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
package sbt.librarymanagement
|
||||
|
||||
import org.apache.ivy.core.module.id.{ ModuleId, ModuleRevisionId }
|
||||
import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor
|
||||
|
||||
import sbt.internal.util.UnitSpec
|
||||
|
||||
import IvyScala.OverrideScalaMediator
|
||||
import ScalaArtifacts._
|
||||
|
||||
class ScalaOverrideTest extends UnitSpec {
|
||||
val OtherOrgID = "other.org"
|
||||
|
||||
def check(org0: String, version0: String)(org1: String, name1: String, version1: String) = {
|
||||
val osm = new OverrideScalaMediator(org0, version0)
|
||||
|
||||
val mrid = ModuleRevisionId.newInstance(org1, name1, version1)
|
||||
val dd = new DefaultDependencyDescriptor(mrid, false)
|
||||
|
||||
val res = osm.mediate(dd)
|
||||
res.getDependencyRevisionId shouldBe ModuleRevisionId.newInstance(org0, name1, version0)
|
||||
}
|
||||
|
||||
"""OverrideScalaMediator
|
||||
""" should "Override compiler version" in check(Organization, "2.11.8")(Organization, CompilerID, "2.11.9")
|
||||
it should "Override library version" in check(Organization, "2.11.8")(Organization, LibraryID, "2.11.8")
|
||||
it should "Override reflect version" in check(Organization, "2.11.8")(Organization, ReflectID, "2.11.7")
|
||||
it should "Override actors version" in check(Organization, "2.11.8")(Organization, ActorsID, "2.11.6")
|
||||
it should "Override scalap version" in check(Organization, "2.11.8")(Organization, ScalapID, "2.11.5")
|
||||
|
||||
it should "Override default compiler organization" in check(OtherOrgID, "2.11.8")(Organization, CompilerID, "2.11.9")
|
||||
it should "Override default library organization" in check(OtherOrgID, "2.11.8")(Organization, LibraryID, "2.11.8")
|
||||
it should "Override default reflect organization" in check(OtherOrgID, "2.11.8")(Organization, ReflectID, "2.11.7")
|
||||
it should "Override default actors organization" in check(OtherOrgID, "2.11.8")(Organization, ActorsID, "2.11.6")
|
||||
it should "Override default scalap organization" in check(OtherOrgID, "2.11.8")(Organization, ScalapID, "2.11.5")
|
||||
|
||||
it should "Override custom compiler organization" in check(Organization, "2.11.8")(OtherOrgID, CompilerID, "2.11.9")
|
||||
it should "Override custom library organization" in check(Organization, "2.11.8")(OtherOrgID, LibraryID, "2.11.8")
|
||||
it should "Override custom reflect organization" in check(Organization, "2.11.8")(OtherOrgID, ReflectID, "2.11.7")
|
||||
it should "Override custom actors organization" in check(Organization, "2.11.8")(OtherOrgID, ActorsID, "2.11.6")
|
||||
it should "Override custom scalap organization" in check(Organization, "2.11.8")(OtherOrgID, ScalapID, "2.11.5")
|
||||
}
|
||||
Loading…
Reference in New Issue