package sbt package ivyint import java.io.File import java.net.URI import java.util.{Collection, Collections => CS} import CS.singleton import org.apache.ivy.{core, plugins, util, Ivy} import core.module.descriptor.{DependencyArtifactDescriptor, DefaultDependencyArtifactDescriptor} import core.module.descriptor.{DefaultDependencyDescriptor => DDD, DependencyDescriptor} import core.module.id.{ArtifactId,ModuleId, ModuleRevisionId} import plugins.namespace.Namespace import util.extendable.ExtendableItem private[sbt] object MergeDescriptors { 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) new MergedDescriptors(a,b) } } // combines the artifacts, configurations, includes, and excludes for DependencyDescriptors `a` and `b` // that otherwise have equal IDs private final class MergedDescriptors(a: DependencyDescriptor, b: DependencyDescriptor) extends DependencyDescriptor { def getDependencyId = a.getDependencyId def isForce = a.isForce def isChanging = a.isChanging def isTransitive = a.isTransitive def getNamespace = a.getNamespace def getParentRevisionId = a.getParentRevisionId def getDependencyRevisionId = a.getDependencyRevisionId def getDynamicConstraintDependencyRevisionId = a.getDynamicConstraintDependencyRevisionId def getModuleConfigurations = concat(a.getModuleConfigurations, b.getModuleConfigurations) def getDependencyConfigurations(moduleConfiguration: String, requestedConfiguration: String) = concat(a.getDependencyConfigurations(moduleConfiguration, requestedConfiguration), b.getDependencyConfigurations(moduleConfiguration)) def getDependencyConfigurations(moduleConfiguration: String) = concat(a.getDependencyConfigurations(moduleConfiguration), b.getDependencyConfigurations(moduleConfiguration)) def getDependencyConfigurations(moduleConfigurations: Array[String]) = concat(a.getDependencyConfigurations(moduleConfigurations), b.getDependencyConfigurations(moduleConfigurations)) def getAllDependencyArtifacts = concatArtifacts(a, a.getAllDependencyArtifacts, b, b.getAllDependencyArtifacts) def getDependencyArtifacts(moduleConfigurations: String) = concatArtifacts(a, a.getDependencyArtifacts(moduleConfigurations), b, b.getDependencyArtifacts(moduleConfigurations)) def getDependencyArtifacts(moduleConfigurations: Array[String]) = concatArtifacts(a, a.getDependencyArtifacts(moduleConfigurations), b, b.getDependencyArtifacts(moduleConfigurations)) def getAllIncludeRules = concat(a.getAllIncludeRules, b.getAllIncludeRules) def getIncludeRules(moduleConfigurations: String) = concat(a.getIncludeRules(moduleConfigurations), b.getIncludeRules(moduleConfigurations)) def getIncludeRules(moduleConfigurations: Array[String]) = concat(a.getIncludeRules(moduleConfigurations), b.getIncludeRules(moduleConfigurations)) private[this] def concatArtifacts(a: DependencyDescriptor, as: Array[DependencyArtifactDescriptor], b: DependencyDescriptor, bs: Array[DependencyArtifactDescriptor]) = { if(as.isEmpty) if(bs.isEmpty) as else defaultArtifact(a) +: explicitConfigurations(b, bs) else if(bs.isEmpty) explicitConfigurations(a, as) :+ defaultArtifact(b) else concat(explicitConfigurations(a, as), explicitConfigurations(b, bs)) } private[this] def explicitConfigurations(base: DependencyDescriptor, arts: Array[DependencyArtifactDescriptor]): Array[DependencyArtifactDescriptor] = arts map { art => explicitConfigurations(base, art) } private[this] def explicitConfigurations(base: DependencyDescriptor, art: DependencyArtifactDescriptor): DependencyArtifactDescriptor = { val aConfs = art.getConfigurations if(aConfs == null || aConfs.isEmpty) copyWithConfigurations(art, base.getModuleConfigurations) else art } private[this] def defaultArtifact(a: DependencyDescriptor): DependencyArtifactDescriptor = { val dd = new DefaultDependencyArtifactDescriptor(a, a.getDependencyRevisionId.getName, "jar", "jar", null, null) addConfigurations(dd, a.getModuleConfigurations) dd } private[this] def copyWithConfigurations(dd: DependencyArtifactDescriptor, confs: Seq[String]): DependencyArtifactDescriptor = { val dextra = dd.getQualifiedExtraAttributes val newd = new DefaultDependencyArtifactDescriptor(dd.getDependencyDescriptor, dd.getName, dd.getType, dd.getExt, dd.getUrl, dextra) addConfigurations(newd, confs) newd } private[this] def addConfigurations(dd: DefaultDependencyArtifactDescriptor, confs: Seq[String]): Unit = confs foreach dd.addConfiguration private[this] def concat[T: ClassManifest](a: Array[T], b: Array[T]): Array[T] = (a ++ b).distinct.toArray def getAllExcludeRules = concat(a.getAllExcludeRules, b.getAllExcludeRules) def getExcludeRules(moduleConfigurations: String) = concat(a.getExcludeRules(moduleConfigurations), b.getExcludeRules(moduleConfigurations)) def getExcludeRules(moduleConfigurations: Array[String]) = concat(a.getExcludeRules(moduleConfigurations), b.getExcludeRules(moduleConfigurations)) def doesExclude(moduleConfigurations: Array[String], artifactId: ArtifactId) = a.doesExclude(moduleConfigurations, artifactId) || b.doesExclude(moduleConfigurations, artifactId) def canExclude = a.canExclude || b.canExclude def asSystem = this def clone(revision: ModuleRevisionId) = new MergedDescriptors(a.clone(revision), b.clone(revision)) def getAttribute(name: String): String = a.getAttribute(name) def getAttributes = a.getAttributes def getExtraAttribute(name: String) = a.getExtraAttribute(name) def getExtraAttributes = a.getExtraAttributes def getQualifiedExtraAttributes = a.getQualifiedExtraAttributes def getSourceModule = a.getSourceModule }