mirror of https://github.com/sbt/sbt.git
This is only a workaround. Multiple dependency definitions should be avoided in general.
This commit is contained in:
parent
f0bdadc437
commit
152d51465d
|
|
@ -64,8 +64,11 @@ object CustomPomParser
|
||||||
// Fixes up the detected extension in some cases missed by Ivy.
|
// Fixes up the detected extension in some cases missed by Ivy.
|
||||||
val convertArtifacts = artifactExtIncorrect(md)
|
val convertArtifacts = artifactExtIncorrect(md)
|
||||||
|
|
||||||
|
// Merges artifact sections for duplicate dependency definitions
|
||||||
|
val mergeDuplicates = IvySbt.hasDuplicateDependencies(md.getDependencies)
|
||||||
|
|
||||||
val unqualify = (filtered - ExtraAttributesKey) map { case (k,v) => ("e:" + k, v) }
|
val unqualify = (filtered - ExtraAttributesKey) map { case (k,v) => ("e:" + k, v) }
|
||||||
if(unqualify.isEmpty && extraDepAttributes.isEmpty && !convertArtifacts)
|
if(unqualify.isEmpty && extraDepAttributes.isEmpty && !convertArtifacts && !mergeDuplicates)
|
||||||
md
|
md
|
||||||
else
|
else
|
||||||
addExtra(unqualify, extraDepAttributes, parser, md)
|
addExtra(unqualify, extraDepAttributes, parser, md)
|
||||||
|
|
@ -74,7 +77,6 @@ object CustomPomParser
|
||||||
md.getConfigurations.exists(conf => md.getArtifacts(conf.getName).exists(art => JarPackagings(art.getExt)))
|
md.getConfigurations.exists(conf => md.getArtifacts(conf.getName).exists(art => JarPackagings(art.getExt)))
|
||||||
private[this] def shouldBeUnqualified(m: Map[String, String]): Map[String, String] =
|
private[this] def shouldBeUnqualified(m: Map[String, String]): Map[String, String] =
|
||||||
m.filter { case (SbtVersionKey | ScalaVersionKey | ExtraAttributesKey,_) => true; case _ => false }
|
m.filter { case (SbtVersionKey | ScalaVersionKey | ExtraAttributesKey,_) => true; case _ => false }
|
||||||
|
|
||||||
|
|
||||||
private[this] def condAddExtra(properties: Map[String, String], id: ModuleRevisionId): ModuleRevisionId =
|
private[this] def condAddExtra(properties: Map[String, String], id: ModuleRevisionId): ModuleRevisionId =
|
||||||
if(properties.isEmpty) id else addExtra(properties, id)
|
if(properties.isEmpty) id else addExtra(properties, id)
|
||||||
|
|
@ -169,7 +171,10 @@ object CustomPomParser
|
||||||
for( (key,value) <- md.getExtraInfo.asInstanceOf[java.util.Map[String,String]].asScala ) dmd.addExtraInfo(key, value)
|
for( (key,value) <- md.getExtraInfo.asInstanceOf[java.util.Map[String,String]].asScala ) dmd.addExtraInfo(key, value)
|
||||||
for( (key, value) <- md.getExtraAttributesNamespaces.asInstanceOf[java.util.Map[String,String]].asScala ) dmd.addExtraAttributeNamespace(key, value)
|
for( (key, value) <- md.getExtraAttributesNamespaces.asInstanceOf[java.util.Map[String,String]].asScala ) dmd.addExtraAttributeNamespace(key, value)
|
||||||
IvySbt.addExtraNamespace(dmd)
|
IvySbt.addExtraNamespace(dmd)
|
||||||
for( dd <- md.getDependencies ) dmd.addDependency(addExtra(dd, dependencyExtra))
|
|
||||||
|
val withExtra = md.getDependencies map { dd => addExtra(dd, dependencyExtra) }
|
||||||
|
val unique = IvySbt.mergeDuplicateDefinitions(withExtra)
|
||||||
|
unique foreach dmd.addDependency
|
||||||
|
|
||||||
for( ed <- md.getInheritedDescriptors) dmd.addInheritedDescriptor( new DefaultExtendsDescriptor( mrid, resolvedMrid, ed.getLocation, ed.getExtendsTypes) )
|
for( ed <- md.getInheritedDescriptors) dmd.addInheritedDescriptor( new DefaultExtendsDescriptor( mrid, resolvedMrid, ed.getLocation, ed.getExtendsTypes) )
|
||||||
for( conf <- md.getConfigurations) {
|
for( conf <- md.getConfigurations) {
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,8 @@ final class IvySbt(val configuration: IvyConfiguration)
|
||||||
val parser = IvySbt.parseIvyXML(ivy.getSettings, IvySbt.wrapped(module, ivyXML), moduleID, defaultConf.name, validate)
|
val parser = IvySbt.parseIvyXML(ivy.getSettings, IvySbt.wrapped(module, ivyXML), moduleID, defaultConf.name, validate)
|
||||||
IvySbt.addMainArtifact(moduleID)
|
IvySbt.addMainArtifact(moduleID)
|
||||||
IvySbt.addOverrides(moduleID, overrides, ivy.getSettings.getMatcher(PatternMatcher.EXACT))
|
IvySbt.addOverrides(moduleID, overrides, ivy.getSettings.getMatcher(PatternMatcher.EXACT))
|
||||||
IvySbt.addDependencies(moduleID, IvySbt.overrideDirect(dependencies, overrides), parser)
|
val transformedDeps = IvySbt.overrideDirect(dependencies, overrides)
|
||||||
|
IvySbt.addDependencies(moduleID, transformedDeps, parser)
|
||||||
(moduleID, parser.getDefaultConf)
|
(moduleID, parser.getDefaultConf)
|
||||||
}
|
}
|
||||||
private def newConfiguredModuleID(module: ModuleID, moduleInfo: ModuleInfo, configurations: Iterable[Configuration]) =
|
private def newConfiguredModuleID(module: ModuleID, moduleInfo: ModuleInfo, configurations: Iterable[Configuration]) =
|
||||||
|
|
@ -423,36 +424,73 @@ private object IvySbt
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This method is used to add inline dependencies to the provided module. */
|
/** This method is used to add inline dependencies to the provided module. */
|
||||||
def addDependencies(moduleID: DefaultModuleDescriptor, dependencies: Iterable[ModuleID], parser: CustomXmlParser.CustomParser)
|
def addDependencies(moduleID: DefaultModuleDescriptor, dependencies: Seq[ModuleID], parser: CustomXmlParser.CustomParser)
|
||||||
{
|
{
|
||||||
for(dependency <- dependencies)
|
val converted = dependencies map { dependency => convertDependency(moduleID, dependency, parser) }
|
||||||
{
|
val unique = if(hasDuplicateDependencies(converted)) mergeDuplicateDefinitions(converted) else converted
|
||||||
val dependencyDescriptor = new DefaultDependencyDescriptor(moduleID, toID(dependency), dependency.isForce, dependency.isChanging, dependency.isTransitive)
|
unique foreach moduleID.addDependency
|
||||||
dependency.configurations match
|
|
||||||
{
|
|
||||||
case None => // The configuration for this dependency was not explicitly specified, so use the default
|
|
||||||
parser.parseDepsConfs(parser.getDefaultConf, dependencyDescriptor)
|
|
||||||
case Some(confs) => // The configuration mapping (looks like: test->default) was specified for this dependency
|
|
||||||
parser.parseDepsConfs(confs, dependencyDescriptor)
|
|
||||||
}
|
|
||||||
for(artifact <- dependency.explicitArtifacts)
|
|
||||||
{
|
|
||||||
import artifact.{name, classifier, `type`, extension, url}
|
|
||||||
val extraMap = extra(artifact)
|
|
||||||
val ivyArtifact = new DefaultDependencyArtifactDescriptor(dependencyDescriptor, name, `type`, extension, url.getOrElse(null), extraMap)
|
|
||||||
for(conf <- dependencyDescriptor.getModuleConfigurations)
|
|
||||||
dependencyDescriptor.addDependencyArtifact(conf, ivyArtifact)
|
|
||||||
}
|
|
||||||
for(excls <- dependency.exclusions)
|
|
||||||
{
|
|
||||||
for(conf <- dependencyDescriptor.getModuleConfigurations)
|
|
||||||
{
|
|
||||||
dependencyDescriptor.addExcludeRule(conf, IvyScala.excludeRule(excls.organization, excls.name, excls.configurations, excls.artifact))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
moduleID.addDependency(dependencyDescriptor)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/** Determines if there are multiple dependency definitions for the same dependency ID. */
|
||||||
|
def hasDuplicateDependencies(dependencies: Seq[DependencyDescriptor]): Boolean =
|
||||||
|
{
|
||||||
|
val ids = dependencies.map(_.getDependencyRevisionId)
|
||||||
|
ids.toSet.size != ids.size
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Combines the artifacts, includes, and excludes of duplicate dependency definitions.
|
||||||
|
* This is somewhat fragile and is only intended to workaround Ivy (or sbt's use of Ivy) not handling this case properly.
|
||||||
|
* In particular, Ivy will create multiple dependency entries when converting a pom with a dependency on a classified artifact and a non-classified artifact:
|
||||||
|
* https://github.com/harrah/xsbt/issues/468
|
||||||
|
* It will also allow users to declare dependencies on classified modules in different configurations:
|
||||||
|
* https://groups.google.com/d/topic/simple-build-tool/H2MdAARz6e0/discussion
|
||||||
|
* as well as basic multi-classifier handling: #285, #419, #480.
|
||||||
|
* Multiple dependency definitions should otherwise be avoided as much as possible.
|
||||||
|
*/
|
||||||
|
def mergeDuplicateDefinitions(dependencies: Seq[DependencyDescriptor]): Seq[DependencyDescriptor] =
|
||||||
|
{
|
||||||
|
val deps = new java.util.LinkedHashMap[ModuleRevisionId, DependencyDescriptor]
|
||||||
|
for( dd <- dependencies )
|
||||||
|
{
|
||||||
|
val id = dd.getDependencyRevisionId
|
||||||
|
val updated = deps get id match {
|
||||||
|
case null => dd
|
||||||
|
case v => ivyint.MergeDescriptors(v, dd)
|
||||||
|
}
|
||||||
|
deps.put(id, updated)
|
||||||
|
}
|
||||||
|
import collection.JavaConverters._
|
||||||
|
deps.values.asScala.toSeq
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Transforms an sbt ModuleID into an Ivy DefaultDependencyDescriptor.*/
|
||||||
|
def convertDependency(moduleID: DefaultModuleDescriptor, dependency: ModuleID, parser: CustomXmlParser.CustomParser): DefaultDependencyDescriptor =
|
||||||
|
{
|
||||||
|
val dependencyDescriptor = new DefaultDependencyDescriptor(moduleID, toID(dependency), dependency.isForce, dependency.isChanging, dependency.isTransitive)
|
||||||
|
dependency.configurations match
|
||||||
|
{
|
||||||
|
case None => // The configuration for this dependency was not explicitly specified, so use the default
|
||||||
|
parser.parseDepsConfs(parser.getDefaultConf, dependencyDescriptor)
|
||||||
|
case Some(confs) => // The configuration mapping (looks like: test->default) was specified for this dependency
|
||||||
|
parser.parseDepsConfs(confs, dependencyDescriptor)
|
||||||
|
}
|
||||||
|
for(artifact <- dependency.explicitArtifacts)
|
||||||
|
{
|
||||||
|
import artifact.{name, classifier, `type`, extension, url}
|
||||||
|
val extraMap = extra(artifact)
|
||||||
|
val ivyArtifact = new DefaultDependencyArtifactDescriptor(dependencyDescriptor, name, `type`, extension, url.getOrElse(null), extraMap)
|
||||||
|
for(conf <- dependencyDescriptor.getModuleConfigurations)
|
||||||
|
dependencyDescriptor.addDependencyArtifact(conf, ivyArtifact)
|
||||||
|
}
|
||||||
|
for(excls <- dependency.exclusions)
|
||||||
|
{
|
||||||
|
for(conf <- dependencyDescriptor.getModuleConfigurations)
|
||||||
|
{
|
||||||
|
dependencyDescriptor.addExcludeRule(conf, IvyScala.excludeRule(excls.organization, excls.name, excls.configurations, excls.artifact))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencyDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
def addOverrides(moduleID: DefaultModuleDescriptor, overrides: Set[ModuleID], matcher: PatternMatcher): Unit =
|
def addOverrides(moduleID: DefaultModuleDescriptor, overrides: Set[ModuleID], matcher: PatternMatcher): Unit =
|
||||||
overrides foreach addOverride(moduleID, matcher)
|
overrides foreach addOverride(moduleID, matcher)
|
||||||
def addOverride(moduleID: DefaultModuleDescriptor, matcher: PatternMatcher)(overrideDef: ModuleID): Unit =
|
def addOverride(moduleID: DefaultModuleDescriptor, matcher: PatternMatcher)(overrideDef: ModuleID): Unit =
|
||||||
|
|
@ -500,6 +538,7 @@ private object IvySbt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** This code converts the given ModuleDescriptor to a DefaultModuleDescriptor by casting or generating an error.
|
/** This code converts the given ModuleDescriptor to a DefaultModuleDescriptor by casting or generating an error.
|
||||||
* Ivy 2.0.0 always produces a DefaultModuleDescriptor. */
|
* Ivy 2.0.0 always produces a DefaultModuleDescriptor. */
|
||||||
private def toDefaultModuleDescriptor(md: ModuleDescriptor) =
|
private def toDefaultModuleDescriptor(md: ModuleDescriptor) =
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ final class PublishConfiguration(val ivyFile: Option[File], val resolverName: St
|
||||||
|
|
||||||
final class UpdateConfiguration(val retrieve: Option[RetrieveConfiguration], val missingOk: Boolean, val logging: UpdateLogging.Value)
|
final class UpdateConfiguration(val retrieve: Option[RetrieveConfiguration], val missingOk: Boolean, val logging: UpdateLogging.Value)
|
||||||
final class RetrieveConfiguration(val retrieveDirectory: File, val outputPattern: String)
|
final class RetrieveConfiguration(val retrieveDirectory: File, val outputPattern: String)
|
||||||
final case class MakePomConfiguration(file: File, moduleInfo: ModuleInfo, configurations: Option[Seq[Configuration]] = None, extra: NodeSeq = NodeSeq.Empty, process: XNode => XNode = n => n, filterRepositories: MavenRepository => Boolean = _ => true, allRepositories: Boolean, includeTypes: Set[String] = Set(Artifact.DefaultType))
|
final case class MakePomConfiguration(file: File, moduleInfo: ModuleInfo, configurations: Option[Seq[Configuration]] = None, extra: NodeSeq = NodeSeq.Empty, process: XNode => XNode = n => n, filterRepositories: MavenRepository => Boolean = _ => true, allRepositories: Boolean, includeTypes: Set[String] = Set(Artifact.DefaultType, Artifact.PomType))
|
||||||
// exclude is a map on a restricted ModuleID
|
// exclude is a map on a restricted ModuleID
|
||||||
final case class GetClassifiersConfiguration(module: GetClassifiersModule, exclude: Map[ModuleID, Set[String]], configuration: UpdateConfiguration, ivyScala: Option[IvyScala])
|
final case class GetClassifiersConfiguration(module: GetClassifiersModule, exclude: Map[ModuleID, Set[String]], configuration: UpdateConfiguration, ivyScala: Option[IvyScala])
|
||||||
final case class GetClassifiersModule(id: ModuleID, modules: Seq[ModuleID], configurations: Seq[Configuration], classifiers: Seq[String])
|
final case class GetClassifiersModule(id: ModuleID, modules: Seq[ModuleID], configurations: Seq[Configuration], classifiers: Seq[String])
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ final case class ModuleID(organization: String, name: String, revision: String,
|
||||||
def extra(attributes: (String,String)*) = copy(extraAttributes = this.extraAttributes ++ ModuleID.checkE(attributes))
|
def extra(attributes: (String,String)*) = copy(extraAttributes = this.extraAttributes ++ ModuleID.checkE(attributes))
|
||||||
def sources() = artifacts(Artifact.sources(name))
|
def sources() = artifacts(Artifact.sources(name))
|
||||||
def javadoc() = artifacts(Artifact.javadoc(name))
|
def javadoc() = artifacts(Artifact.javadoc(name))
|
||||||
|
def pomOnly() = artifacts(Artifact.pom(name))
|
||||||
def withSources() = jarIfEmpty.sources()
|
def withSources() = jarIfEmpty.sources()
|
||||||
def withJavadoc() = jarIfEmpty.javadoc()
|
def withJavadoc() = jarIfEmpty.javadoc()
|
||||||
private def jarIfEmpty = if(explicitArtifacts.isEmpty) jar() else this
|
private def jarIfEmpty = if(explicitArtifacts.isEmpty) jar() else this
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,12 @@ package sbt
|
||||||
import java.io.File
|
import java.io.File
|
||||||
// Node needs to be renamed to XNode because the task subproject contains a Node type that will shadow
|
// Node needs to be renamed to XNode because the task subproject contains a Node type that will shadow
|
||||||
// scala.xml.Node when generating aggregated API documentation
|
// scala.xml.Node when generating aggregated API documentation
|
||||||
import scala.xml.{Node => XNode, NodeSeq, PrettyPrinter}
|
import scala.xml.{Elem, Node => XNode, NodeSeq, PrettyPrinter}
|
||||||
import Configurations.Optional
|
import Configurations.Optional
|
||||||
|
|
||||||
import org.apache.ivy.{core, plugins, Ivy}
|
import org.apache.ivy.{core, plugins, Ivy}
|
||||||
import core.settings.IvySettings
|
import core.settings.IvySettings
|
||||||
import core.module.descriptor
|
import core.module.descriptor.{DependencyArtifactDescriptor, DependencyDescriptor, License, ModuleDescriptor, ExcludeRule}
|
||||||
import descriptor.{DependencyDescriptor, License, ModuleDescriptor, ExcludeRule}
|
|
||||||
import plugins.resolver.{ChainResolver, DependencyResolver, IBiblioResolver}
|
import plugins.resolver.{ChainResolver, DependencyResolver, IBiblioResolver}
|
||||||
|
|
||||||
class MakePom(val log: Logger)
|
class MakePom(val log: Logger)
|
||||||
|
|
@ -146,38 +145,75 @@ class MakePom(val log: Logger)
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
def makeDependency(dependency: DependencyDescriptor, includeTypes: Set[String]): NodeSeq =
|
def makeDependency(dependency: DependencyDescriptor, includeTypes: Set[String]): NodeSeq =
|
||||||
|
{
|
||||||
|
val artifacts = dependency.getAllDependencyArtifacts
|
||||||
|
val includeArtifacts = artifacts.filter(d => includeTypes(d.getType))
|
||||||
|
if(artifacts.isEmpty) {
|
||||||
|
val (scope, optional) = getScopeAndOptional(dependency.getModuleConfigurations)
|
||||||
|
makeDependencyElem(dependency, scope, optional, None, None)
|
||||||
|
}
|
||||||
|
else if(includeArtifacts.isEmpty)
|
||||||
|
NodeSeq.Empty
|
||||||
|
else
|
||||||
|
NodeSeq.fromSeq(artifacts.map( a => makeDependencyElem(dependency, a) ))
|
||||||
|
}
|
||||||
|
|
||||||
|
def makeDependencyElem(dependency: DependencyDescriptor, artifact: DependencyArtifactDescriptor): Elem =
|
||||||
|
{
|
||||||
|
val artifactConfigs = artifact.getConfigurations
|
||||||
|
val configs = if(artifactConfigs.isEmpty) dependency.getModuleConfigurations else artifactConfigs
|
||||||
|
val (scope, optional) = getScopeAndOptional(configs)
|
||||||
|
makeDependencyElem(dependency, scope, optional, artifactClassifier(artifact), artifactType(artifact))
|
||||||
|
}
|
||||||
|
def makeDependencyElem(dependency: DependencyDescriptor, scope: Option[String], optional: Boolean, classifier: Option[String], tpe: Option[String]): Elem =
|
||||||
{
|
{
|
||||||
val mrid = dependency.getDependencyRevisionId
|
val mrid = dependency.getDependencyRevisionId
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>{mrid.getOrganisation}</groupId>
|
<groupId>{mrid.getOrganisation}</groupId>
|
||||||
<artifactId>{mrid.getName}</artifactId>
|
<artifactId>{mrid.getName}</artifactId>
|
||||||
<version>{mrid.getRevision}</version>
|
<version>{mrid.getRevision}</version>
|
||||||
{ scopeAndOptional(dependency) }
|
{ scopeElem(scope) }
|
||||||
{ classifier(dependency, includeTypes) }
|
{ optionalElem(optional) }
|
||||||
|
{ classifierElem(classifier) }
|
||||||
|
{ typeElem(tpe) }
|
||||||
{ exclusions(dependency) }
|
{ exclusions(dependency) }
|
||||||
</dependency>
|
</dependency>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@deprecated("No longer used and will be removed.", "0.12.1")
|
||||||
def classifier(dependency: DependencyDescriptor, includeTypes: Set[String]): NodeSeq =
|
def classifier(dependency: DependencyDescriptor, includeTypes: Set[String]): NodeSeq =
|
||||||
{
|
{
|
||||||
val jarDep = dependency.getAllDependencyArtifacts.filter(d => includeTypes(d.getType)).headOption
|
val jarDep = dependency.getAllDependencyArtifacts.filter(d => includeTypes(d.getType)).headOption
|
||||||
jarDep match {
|
jarDep match {
|
||||||
case Some(a) => {
|
case Some(a) => classifierElem(artifactClassifier(a))
|
||||||
val cl = a.getExtraAttribute("classifier")
|
case None => NodeSeq.Empty
|
||||||
if (cl != null) <classifier>{cl}</classifier> else NodeSeq.Empty
|
|
||||||
}
|
|
||||||
case _ => NodeSeq.Empty
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
def artifactType(artifact: DependencyArtifactDescriptor): Option[String] =
|
||||||
|
Option(artifact.getType).flatMap { tpe => if(tpe == "jar") None else Some(tpe) }
|
||||||
|
def typeElem(tpe: Option[String]): NodeSeq =
|
||||||
|
tpe match {
|
||||||
|
case Some(t) => <type>{t}</type>
|
||||||
|
case None => NodeSeq.Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
def artifactClassifier(artifact: DependencyArtifactDescriptor): Option[String] =
|
||||||
|
Option(artifact.getExtraAttribute("classifier"))
|
||||||
|
def classifierElem(classifier: Option[String]): NodeSeq =
|
||||||
|
classifier match {
|
||||||
|
case Some(c) => <classifier>{c}</classifier>
|
||||||
|
case None => NodeSeq.Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
@deprecated("No longer used and will be removed.", "0.12.1")
|
||||||
def scopeAndOptional(dependency: DependencyDescriptor): NodeSeq =
|
def scopeAndOptional(dependency: DependencyDescriptor): NodeSeq =
|
||||||
{
|
{
|
||||||
val (scope, opt) = getScopeAndOptional(dependency.getModuleConfigurations)
|
val (scope, opt) = getScopeAndOptional(dependency.getModuleConfigurations)
|
||||||
scopeElem(scope) ++ optionalElem(opt)
|
scopeElem(scope) ++ optionalElem(opt)
|
||||||
}
|
}
|
||||||
def scopeElem(scope: Option[String]): NodeSeq = scope match {
|
def scopeElem(scope: Option[String]): NodeSeq = scope match {
|
||||||
case Some(s) => <scope>{s}</scope>
|
|
||||||
case None => NodeSeq.Empty
|
case None => NodeSeq.Empty
|
||||||
|
case Some(s) => <scope>{s}</scope>
|
||||||
}
|
}
|
||||||
def optionalElem(opt: Boolean) = if(opt) <optional>true</optional> else NodeSeq.Empty
|
def optionalElem(opt: Boolean) = if(opt) <optional>true</optional> else NodeSeq.Empty
|
||||||
def moduleDescriptor(module: ModuleDescriptor) = module.getModuleRevisionId
|
def moduleDescriptor(module: ModuleDescriptor) = module.getModuleRevisionId
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
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
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue