Merge pull request #44 from milessabin/topic/scala-override

Override scala organization and version transitively at the Ivy level
This commit is contained in:
eugene yokota 2016-06-03 13:15:51 -04:00
commit d2e6133704
4 changed files with 101 additions and 16 deletions

View File

@ -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

View File

@ -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
)
}

View File

@ -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() = {

View File

@ -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")
}