From 5523d16a77d15c9d1d1d6134a9d103dd49a5380b Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Fri, 11 Jan 2013 16:01:31 -0500 Subject: [PATCH] Configurable conflict manager and corresponding documentation on conflictManager, dependencyOverrides, and force(). Fixes #603. --- ivy/src/main/scala/sbt/Ivy.scala | 10 +++++++++- ivy/src/main/scala/sbt/IvyConfigurations.scala | 2 +- ivy/src/main/scala/sbt/IvyInterface.scala | 18 +++++++++++++++--- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/ivy/src/main/scala/sbt/Ivy.scala b/ivy/src/main/scala/sbt/Ivy.scala index 3ffb8121d..0414cb0c5 100644 --- a/ivy/src/main/scala/sbt/Ivy.scala +++ b/ivy/src/main/scala/sbt/Ivy.scala @@ -20,7 +20,6 @@ import core.module.descriptor.{OverrideDependencyDescriptorMediator} import core.module.id.{ArtifactId,ModuleId, ModuleRevisionId} import core.resolve.{IvyNode, ResolveData, ResolvedModuleRevision} import core.settings.IvySettings -import plugins.conflict.{ConflictManager, LatestCompatibleConflictManager, LatestConflictManager} import plugins.latest.LatestRevisionStrategy import plugins.matcher.PatternMatcher import plugins.parser.m2.PomModuleDescriptorParser @@ -140,6 +139,7 @@ final class IvySbt(val configuration: IvyConfiguration) { import ic._ val moduleID = newConfiguredModuleID(module, moduleInfo, configurations) + IvySbt.setConflictManager(moduleID, conflictManager, ivy.getSettings) val defaultConf = defaultConfiguration getOrElse Configurations.config(ModuleDescriptor.DEFAULT_CONFIGURATION) log.debug("Using inline dependencies specified in Scala" + (if(ivyXML.isEmpty) "." else " and XML.")) @@ -359,6 +359,14 @@ private object IvySbt moduleID.setModuleArtifact(artifact) moduleID.check() } + private def setConflictManager(moduleID: DefaultModuleDescriptor, conflict: ConflictManager, is: IvySettings) + { + val mid = ModuleId.newInstance(conflict.organization, conflict.module) + val matcher = is.getMatcher(PatternMatcher.EXACT_OR_REGEXP) + val manager = is.getConflictManager(conflict.name) + moduleID.addConflictManager(mid, matcher, manager) + } + /** Converts the given sbt module id into an Ivy ModuleRevisionId.*/ def toID(m: ModuleID) = { diff --git a/ivy/src/main/scala/sbt/IvyConfigurations.scala b/ivy/src/main/scala/sbt/IvyConfigurations.scala index f46d24dbd..256af5f2e 100644 --- a/ivy/src/main/scala/sbt/IvyConfigurations.scala +++ b/ivy/src/main/scala/sbt/IvyConfigurations.scala @@ -74,7 +74,7 @@ final case class PomConfiguration(file: File, ivyScala: Option[IvyScala], valida { def noScala = copy(ivyScala = None) } -final case class InlineConfiguration(module: ModuleID, moduleInfo: ModuleInfo, dependencies: Seq[ModuleID], overrides: Set[ModuleID] = Set.empty, ivyXML: NodeSeq = NodeSeq.Empty, configurations: Seq[Configuration] = Nil, defaultConfiguration: Option[Configuration] = None, ivyScala: Option[IvyScala] = None, validate: Boolean = false) extends ModuleSettings +final case class InlineConfiguration(module: ModuleID, moduleInfo: ModuleInfo, dependencies: Seq[ModuleID], overrides: Set[ModuleID] = Set.empty, ivyXML: NodeSeq = NodeSeq.Empty, configurations: Seq[Configuration] = Nil, defaultConfiguration: Option[Configuration] = None, ivyScala: Option[IvyScala] = None, validate: Boolean = false, conflictManager: ConflictManager = ConflictManager.default) extends ModuleSettings { def withConfigurations(configurations: Seq[Configuration]) = copy(configurations = configurations) def noScala = copy(ivyScala = None) diff --git a/ivy/src/main/scala/sbt/IvyInterface.scala b/ivy/src/main/scala/sbt/IvyInterface.scala index a1a651e55..2772b98c3 100644 --- a/ivy/src/main/scala/sbt/IvyInterface.scala +++ b/ivy/src/main/scala/sbt/IvyInterface.scala @@ -10,7 +10,7 @@ import org.apache.ivy.plugins.resolver.{DependencyResolver, IBiblioResolver} import org.apache.ivy.util.url.CredentialsStore /** Additional information about a project module */ -case class ModuleInfo(nameFormal: String, description: String = "", homepage: Option[URL] = None, startYear: Option[Int] = None, licenses: Seq[(String, URL)] = Nil, organizationName: String = "", organizationHomepage: Option[URL] = None, scmInfo: Option[ScmInfo] = None) +final case class ModuleInfo(nameFormal: String, description: String = "", homepage: Option[URL] = None, startYear: Option[Int] = None, licenses: Seq[(String, URL)] = Nil, organizationName: String = "", organizationHomepage: Option[URL] = None, scmInfo: Option[ScmInfo] = None) { def formally(name: String) = copy(nameFormal = name) def describing(desc: String, home: Option[URL]) = copy(description = desc, homepage = home) @@ -19,10 +19,10 @@ case class ModuleInfo(nameFormal: String, description: String = "", homepage: Op } /** Basic SCM information for a project module */ -case class ScmInfo(browseUrl: URL, connection: String, devConnection: Option[String] = None) +final case class ScmInfo(browseUrl: URL, connection: String, devConnection: Option[String] = None) /** Rule to exclude unwanted dependencies pulled in transitively by a module. */ -case class ExclusionRule(organization: String = "*", name: String = "*", artifact: String = "*", configurations: Seq[String] = Nil) +final case class ExclusionRule(organization: String = "*", name: String = "*", artifact: String = "*", configurations: Seq[String] = Nil) final case class ModuleConfiguration(organization: String, name: String, revision: String, resolver: Resolver) object ModuleConfiguration @@ -30,3 +30,15 @@ object ModuleConfiguration def apply(org: String, resolver: Resolver): ModuleConfiguration = apply(org, "*", "*", resolver) def apply(org: String, name: String, resolver: Resolver): ModuleConfiguration = ModuleConfiguration(org, name, "*", resolver) } + +final case class ConflictManager(name: String, organization: String = "*", module: String = "*") + +/** See http://ant.apache.org/ivy/history/latest-milestone/settings/conflict-managers.html for details of the different conflict managers.*/ +object ConflictManager { + val all = ConflictManager("all") + val latestTime = ConflictManager("latest-time") + val latestRevision = ConflictManager("latest-revision") + val latestCompatible = ConflictManager("latest-compatible") + val strict = ConflictManager("strict") + val default = latestRevision +} \ No newline at end of file