Fixes #582. Don't merge dependencies with mismatched transitive/force/changing values.

This avoids the assertion, but note that Ivy is unlikely to work properly in this situation.
This commit is contained in:
Mark Harrah 2012-11-12 14:45:23 -05:00
parent 761a441805
commit ce0284e187
4 changed files with 44 additions and 16 deletions

View File

@ -474,18 +474,23 @@ private object IvySbt
*/
def mergeDuplicateDefinitions(dependencies: Seq[DependencyDescriptor]): Seq[DependencyDescriptor] =
{
val deps = new java.util.LinkedHashMap[ModuleRevisionId, DependencyDescriptor]
// need to preserve basic order of dependencies: can't use dependencies.groupBy
val deps = new java.util.LinkedHashMap[ModuleRevisionId, List[DependencyDescriptor]]
for( dd <- dependencies )
{
val id = dd.getDependencyRevisionId
val updated = deps get id match {
case null => dd
case v => ivyint.MergeDescriptors(v, dd)
case null => dd :: Nil
case v => dd :: v
}
deps.put(id, updated)
}
import collection.JavaConverters._
deps.values.asScala.toSeq
deps.values.asScala.toSeq.flatMap { dds =>
val mergeable = (dds, dds.tail).zipped.forall( ivyint.MergeDescriptors.mergeable _)
if(mergeable) dds.reverse.reduceLeft(ivyint.MergeDescriptors.apply _) :: Nil else dds
}
}
/** Transforms an sbt ModuleID into an Ivy DefaultDependencyDescriptor.*/

View File

@ -15,20 +15,24 @@ import util.extendable.ExtendableItem
private[sbt] object MergeDescriptors
{
def mergeable(a: DependencyDescriptor, b: DependencyDescriptor): Boolean =
a.isForce == b.isForce &&
a.isChanging == b.isChanging &&
a.isTransitive == b.isTransitive &&
a.getParentRevisionId == b.getParentRevisionId &&
a.getNamespace == b.getNamespace && {
val amrid = a.getDependencyRevisionId
val bmrid = b.getDependencyRevisionId
amrid == bmrid
} && {
val adyn = a.getDynamicConstraintDependencyRevisionId
val bdyn = b.getDynamicConstraintDependencyRevisionId
adyn == bdyn
}
def apply(a: DependencyDescriptor, b: DependencyDescriptor): DependencyDescriptor =
{
assert(a.isForce == b.isForce)
assert(a.isChanging == b.isChanging)
assert(a.isTransitive == b.isTransitive)
assert(a.getParentRevisionId == b.getParentRevisionId)
val amrid = a.getDependencyRevisionId
val bmrid = b.getDependencyRevisionId
assert(amrid == bmrid)
val adyn = a.getDynamicConstraintDependencyRevisionId
val bdyn = b.getDynamicConstraintDependencyRevisionId
assert(adyn == bdyn)
assert(a.getNamespace == b.getNamespace)
assert(mergeable(a,b))
new MergedDescriptors(a,b)
}
}

View File

@ -0,0 +1,13 @@
libraryDependencies ++= Seq(
"org.easytesting" % "fest-assert" % "1.4",
"org.easytesting" % "fest-assert" % "1.4" % "test" intransitive())
autoScalaLibrary := false
TaskKey[Unit]("check") <<= (externalDependencyClasspath in Compile, externalDependencyClasspath in Test) map { (cp, tcp) =>
assert(cp.size == 2, "Expected 2 jars on compile classpath, got: " + cp.files.mkString("(", ", ", ")"))
// this should really be 1 because of intransitive(), but Ivy doesn't handle this.
// So, this test can only check that the assertion reported in #582 isn't triggered.
assert(tcp.size == 2, "Expected 2 jar on test classpath, got: " + tcp.files.mkString("(", ", ", ")"))
}

View File

@ -1,3 +1,9 @@
> check
> check-pom
$ delete build.sbt
$ copy-file changes/non-mergeable.sbt build.sbt
> reload
> check