diff --git a/ivy/src/main/scala/sbt/ivyint/CachedResolutionResolveEngine.scala b/ivy/src/main/scala/sbt/ivyint/CachedResolutionResolveEngine.scala index 120e3042c..15c3e3b79 100644 --- a/ivy/src/main/scala/sbt/ivyint/CachedResolutionResolveEngine.scala +++ b/ivy/src/main/scala/sbt/ivyint/CachedResolutionResolveEngine.scala @@ -12,7 +12,7 @@ import core.resolve._ import core.module.id.{ ModuleRevisionId, ModuleId => IvyModuleId } import core.report.{ ResolveReport, ConfigurationResolveReport, DownloadReport } import core.module.descriptor.{ DefaultModuleDescriptor, ModuleDescriptor, DefaultDependencyDescriptor, DependencyDescriptor, Configuration => IvyConfiguration, ExcludeRule, IncludeRule } -import core.module.descriptor.OverrideDependencyDescriptorMediator +import core.module.descriptor.{ OverrideDependencyDescriptorMediator, DependencyArtifactDescriptor } import core.{ IvyPatternHelper, LogOptions } import org.apache.ivy.util.Message import org.apache.ivy.plugins.latest.{ ArtifactInfo => IvyArtifactInfo } @@ -37,33 +37,38 @@ private[sbt] class CachedResolutionResolveCache() { } def directDependencies(md0: ModuleDescriptor): Vector[DependencyDescriptor] = md0.getDependencies.toVector - def buildArtificialModuleDescriptors(md0: ModuleDescriptor, data: ResolveData, prOpt: Option[ProjectResolver]): Vector[(DefaultModuleDescriptor, Boolean)] = + def buildArtificialModuleDescriptors(md0: ModuleDescriptor, data: ResolveData, prOpt: Option[ProjectResolver], log: Logger): Vector[(DefaultModuleDescriptor, Boolean)] = { + log.debug(s":: building artificial module descriptors from ${md0.getModuleRevisionId}") + val expanded = expandInternalDependencies(md0, data, prOpt, log) val rootModuleConfigs = md0.getConfigurations.toArray.toVector - val expanded = expandInternalDependencies(md0, data, prOpt) - expanded map { buildArtificialModuleDescriptor(_, rootModuleConfigs, md0, prOpt) } + expanded map { buildArtificialModuleDescriptor(_, rootModuleConfigs, md0, prOpt, log) } } // This expands out all internal dependencies and merge them into a single graph that consists // only of external dependencies. // The tricky part is the merger of configurations, even though in most cases we will only see compile->compile when it comes to internal deps. // Theoretically, there could be a potential for test->test->runtime kind of situation. nextConfMap and remapConfigurations track // the configuration chains transitively. - def expandInternalDependencies(md0: ModuleDescriptor, data: ResolveData, prOpt: Option[ProjectResolver]): Vector[DependencyDescriptor] = + def expandInternalDependencies(md0: ModuleDescriptor, data: ResolveData, prOpt: Option[ProjectResolver], log: Logger): Vector[DependencyDescriptor] = { + log.debug(s"::: expanding internal dependencies of module descriptor ${md0.getModuleRevisionId}") val rootModuleConfigs = md0.getConfigurations.toArray.toVector val rootNode = new IvyNode(data, md0) def expandInternalDeps(dep: DependencyDescriptor, confMap: Map[String, Array[String]]): Vector[DependencyDescriptor] = internalDependency(dep) match { case Some(internal) => + log.debug(s""":::: found internal dependency ${internal.getResolvedModuleRevisionId}""") val allConfigurations: Vector[String] = (if (confMap.isEmpty) nextConfMap(dep, confMap) else confMap).values.flatten.toList.distinct.toVector - directDependencies(internal) filter { dd => + val next = nextConfMap(dep, confMap) + val directs = directDependencies(internal) filter { dd => allConfigurations exists { conf => !dd.getDependencyConfigurations(conf).isEmpty } - } flatMap { dd => expandInternalDeps(dd, nextConfMap(dd, confMap)) } + } + directs flatMap { dd => expandInternalDeps(dd, next) } case _ => if (confMap.isEmpty) Vector(dep) - else Vector(remapConfigurations(dep, confMap)) + else Vector(remapConfigurations(dep, confMap, log)) } def internalDependency(dep: DependencyDescriptor): Option[ModuleDescriptor] = prOpt match { @@ -88,32 +93,44 @@ private[sbt] class CachedResolutionResolveCache() { } }) } - def remapConfigurations(dd0: DependencyDescriptor, confMap: Map[String, Array[String]]): DependencyDescriptor = + def remapConfigurations(dd0: DependencyDescriptor, confMap: Map[String, Array[String]], log: Logger): DependencyDescriptor = { + log.debug(s""":::: remapping configuration of ${dd0} with ${confMap.toList map { case (k, v) => (k, v.toList) }}""") val dd = new DefaultDependencyDescriptor(md0, dd0.getDependencyRevisionId, dd0.getDynamicConstraintDependencyRevisionId, dd0.isForce, dd0.isChanging, dd0.isTransitive) + val moduleConfigurations = dd0.getModuleConfigurations.toVector for { - moduleConf <- dd0.getModuleConfigurations - (rootModuleConf, vs) <- confMap + moduleConf <- moduleConfigurations + (rootModuleConf, vs) <- confMap.toSeq } if (vs contains moduleConf) { - // moduleConf in dd0 maps to rootModuleConf in dd + log.debug(s""":::: ${dd0}: $moduleConf maps to $rootModuleConf""") dd0.getDependencyConfigurations(moduleConf) foreach { conf => dd.addDependencyConfiguration(rootModuleConf, conf) } + dd0.getIncludeRules(moduleConf) foreach { rule => + dd.addIncludeRule(rootModuleConf, rule) + } dd0.getExcludeRules(moduleConf) foreach { rule => dd.addExcludeRule(rootModuleConf, rule) } + dd0.getDependencyArtifacts(moduleConf) foreach { dad => + dd.addDependencyArtifact(rootModuleConf, dad) + } } + log.debug(s""":::: remapped dd: $dd""") dd } directDependencies(md0) flatMap { dep => expandInternalDeps(dep, Map()) } } - def buildArtificialModuleDescriptor(dd: DependencyDescriptor, rootModuleConfigs: Vector[IvyConfiguration], parent: ModuleDescriptor, prOpt: Option[ProjectResolver]): (DefaultModuleDescriptor, Boolean) = + def buildArtificialModuleDescriptor(dd: DependencyDescriptor, rootModuleConfigs: Vector[IvyConfiguration], + parent: ModuleDescriptor, prOpt: Option[ProjectResolver], log: Logger): (DefaultModuleDescriptor, Boolean) = { def excludeRuleString(rule: ExcludeRule): String = s"""Exclude(${rule.getId},${rule.getConfigurations.mkString(",")},${rule.getMatcher})""" def includeRuleString(rule: IncludeRule): String = s"""Include(${rule.getId},${rule.getConfigurations.mkString(",")},${rule.getMatcher})""" + def artifactString(dad: DependencyArtifactDescriptor): String = + s"""Artifact(${dad.getName},${dad.getType},${dad.getExt},${dad.getUrl},${dad.getConfigurations.mkString(",")})""" val mrid = dd.getDependencyRevisionId val confMap = (dd.getModuleConfigurations map { conf => conf + "->(" + dd.getDependencyConfigurations(conf).mkString(",") + ")" @@ -130,6 +147,13 @@ private[sbt] class CachedResolutionResolveCache() { case rules => Some(conf + "->(" + (rules map includeRuleString).mkString(",") + ")") } }) + val explicitArtifacts = (dd.getModuleConfigurations.toVector flatMap { conf => + dd.getDependencyArtifacts(conf).toVector match { + case Vector() => None + case dads => Some(conf + "->(" + (dads map artifactString).mkString(",") + ")") + } + }) + val mes = parent.getAllExcludeRules.toVector val mesStr = (mes map excludeRuleString).mkString(",") val os = extractOverrides(parent) @@ -281,7 +305,7 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine { val os = cache.extractOverrides(md0) val options1 = new ResolveOptions(options0) val data = new ResolveData(this, options1) - val mds = cache.buildArtificialModuleDescriptors(md0, data, projectResolver) + val mds = cache.buildArtificialModuleDescriptors(md0, data, projectResolver, log) def doWork(md: ModuleDescriptor): Either[ResolveException, UpdateReport] = { val options1 = new ResolveOptions(options0) diff --git a/project/Sbt.scala b/project/Sbt.scala index 354342448..0c23ce6d2 100644 --- a/project/Sbt.scala +++ b/project/Sbt.scala @@ -17,7 +17,7 @@ object Sbt extends Build { s"all control/$task collections/$task io/$task completion/$task" def buildSettings = Seq( organization := "org.scala-sbt", - version := "0.13.7-RC3", + version := "0.13.7-SNAPSHOT", publishArtifact in packageDoc := false, scalaVersion := "2.10.4", publishMavenStyle := false, diff --git a/sbt/src/sbt-test/dependency-management/cached-resolution-basic/a/A.java b/sbt/src/sbt-test/dependency-management/cached-resolution-classifier/a/A.java similarity index 100% rename from sbt/src/sbt-test/dependency-management/cached-resolution-basic/a/A.java rename to sbt/src/sbt-test/dependency-management/cached-resolution-classifier/a/A.java diff --git a/sbt/src/sbt-test/dependency-management/cached-resolution-basic/c/C.java b/sbt/src/sbt-test/dependency-management/cached-resolution-classifier/c/C.java similarity index 100% rename from sbt/src/sbt-test/dependency-management/cached-resolution-basic/c/C.java rename to sbt/src/sbt-test/dependency-management/cached-resolution-classifier/c/C.java diff --git a/sbt/src/sbt-test/dependency-management/cached-resolution-basic/multi.sbt b/sbt/src/sbt-test/dependency-management/cached-resolution-classifier/multi.sbt similarity index 72% rename from sbt/src/sbt-test/dependency-management/cached-resolution-basic/multi.sbt rename to sbt/src/sbt-test/dependency-management/cached-resolution-classifier/multi.sbt index 40805eff0..fceefc6de 100644 --- a/sbt/src/sbt-test/dependency-management/cached-resolution-basic/multi.sbt +++ b/sbt/src/sbt-test/dependency-management/cached-resolution-classifier/multi.sbt @@ -8,31 +8,45 @@ def commonSettings: Seq[Def.Setting[_]] = resolvers += Resolver.sonatypeRepo("snapshots") ) +lazy val classifierTest = project. + settings(commonSettings: _*). + settings( + libraryDependencies := Seq( + "net.sf.json-lib" % "json-lib" % "2.4" classifier "jdk15" intransitive() + ) + ) + +lazy val transitiveTest = project. + settings(commonSettings: _*). + settings( + libraryDependencies := Seq( + "junit" % "junit" % "4.11" % "test" + ) + ) + lazy val a = project. + dependsOn(classifierTest, transitiveTest % "test->test"). settings(commonSettings: _*). settings( updateOptions := updateOptions.value.withCachedResolution(true), artifact in (Compile, packageBin) := Artifact("demo"), libraryDependencies := Seq( - "net.sf.json-lib" % "json-lib" % "2.4" classifier "jdk15" intransitive(), "com.typesafe.akka" %% "akka-remote" % "2.3.4" exclude("com.typesafe.akka", "akka-actor_2.10"), "net.databinder" %% "unfiltered-uploads" % "0.8.0", "commons-io" % "commons-io" % "1.3", - "com.typesafe" % "config" % "0.4.9-SNAPSHOT", - "junit" % "junit" % "4.11" % "test" + "com.typesafe" % "config" % "0.4.9-SNAPSHOT" ) ) lazy val b = project. + dependsOn(classifierTest, transitiveTest % "test->test"). settings(commonSettings: _*). settings( libraryDependencies := Seq( - "net.sf.json-lib" % "json-lib" % "2.4" classifier "jdk15" intransitive(), "com.typesafe.akka" %% "akka-remote" % "2.3.4" exclude("com.typesafe.akka", "akka-actor_2.10"), "net.databinder" %% "unfiltered-uploads" % "0.8.0", "commons-io" % "commons-io" % "1.3", - "com.typesafe" % "config" % "0.4.9-SNAPSHOT", - "junit" % "junit" % "4.11" % "test" + "com.typesafe" % "config" % "0.4.9-SNAPSHOT" ) ) @@ -51,6 +65,9 @@ lazy val root = (project in file(".")). val acp = (externalDependencyClasspath in Compile in a).value.sortBy {_.data.getName} val bcp = (externalDependencyClasspath in Compile in b).value.sortBy {_.data.getName} val ccp = (externalDependencyClasspath in Compile in c).value.sortBy {_.data.getName} filterNot { _.data.getName == "demo_2.10.jar"} + + val atestcp = (externalDependencyClasspath in Test in a).value.sortBy {_.data.getName} + val btestcp = (externalDependencyClasspath in Test in b).value.sortBy {_.data.getName} val ctestcp = (externalDependencyClasspath in Test in c).value.sortBy {_.data.getName} filterNot { _.data.getName == "demo_2.10.jar"} if (ctestcp exists { _.data.getName contains "junit-4.11.jar" }) { sys.error("junit found when it should be excluded: " + ctestcp.toString) @@ -59,6 +76,11 @@ lazy val root = (project in file(".")). else sys.error("Different classpaths are found:" + "\n - a (cached) " + acp.toString + "\n - b (plain) " + bcp.toString + - "\n - c (inter-project) " + ccp.toString) + "\n - c (inter-project) " + ccp.toString) + + if (atestcp == btestcp) () + else sys.error("Different classpaths are found:" + + "\n - a test (cached) " + atestcp.toString + + "\n - b test (plain) " + btestcp.toString) } ) diff --git a/sbt/src/sbt-test/dependency-management/cached-resolution-basic/test b/sbt/src/sbt-test/dependency-management/cached-resolution-classifier/test similarity index 88% rename from sbt/src/sbt-test/dependency-management/cached-resolution-basic/test rename to sbt/src/sbt-test/dependency-management/cached-resolution-classifier/test index 93a09a407..55cfc0713 100644 --- a/sbt/src/sbt-test/dependency-management/cached-resolution-basic/test +++ b/sbt/src/sbt-test/dependency-management/cached-resolution-classifier/test @@ -1,3 +1,5 @@ +> a/update + > a/updateClassifiers > a/publishLocal