diff --git a/ivy/src/main/scala/sbt/MakePom.scala b/ivy/src/main/scala/sbt/MakePom.scala
index 16bd6002a..1dfa5d1fe 100644
--- a/ivy/src/main/scala/sbt/MakePom.scala
+++ b/ivy/src/main/scala/sbt/MakePom.scala
@@ -104,7 +104,7 @@ class MakePom(val log: Logger) {
{
val deps = depsInConfs(module, configurations)
makeProperties(module, deps) ++
- makeDependencies(deps, includeTypes)
+ makeDependencies(deps, includeTypes, module.getAllExcludeRules)
}
{ makeRepositories(ivy.getSettings, allRepositories, filterRepositories) }
)
@@ -220,37 +220,49 @@ class MakePom(val log: Logger) {
}
val IgnoreTypes: Set[String] = Set(Artifact.SourceType, Artifact.DocType, Artifact.PomType)
+ @deprecated("Use `makeDependencies` variant which takes excludes", "0.13.9")
def makeDependencies(dependencies: Seq[DependencyDescriptor], includeTypes: Set[String]): NodeSeq =
+ makeDependencies(dependencies, includeTypes, Nil)
+
+ def makeDependencies(dependencies: Seq[DependencyDescriptor], includeTypes: Set[String], excludes: Seq[ExcludeRule]): NodeSeq =
if (dependencies.isEmpty)
NodeSeq.Empty
else
- { dependencies.map(makeDependency(_, includeTypes)) }
+ { dependencies.map(makeDependency(_, includeTypes, excludes)) }
+ @deprecated("Use `makeDependency` variant which takes excludes", "0.13.9")
def makeDependency(dependency: DependencyDescriptor, includeTypes: Set[String]): NodeSeq =
+ makeDependency(dependency, includeTypes, Nil)
+
+ def makeDependency(dependency: DependencyDescriptor, includeTypes: Set[String], excludes: Seq[ExcludeRule]): NodeSeq =
{
val artifacts = dependency.getAllDependencyArtifacts
val includeArtifacts = artifacts.filter(d => includeTypes(d.getType))
if (artifacts.isEmpty) {
val configs = dependency.getModuleConfigurations
- if (configs.filterNot(Set("sources","docs")).nonEmpty) {
+ if (configs.filterNot(Set("sources", "docs")).nonEmpty) {
val (scope, optional) = getScopeAndOptional(dependency.getModuleConfigurations)
- makeDependencyElem(dependency, scope, optional, None, None)
+ makeDependencyElem(dependency, scope, optional, None, None, excludes)
} else NodeSeq.Empty
} else if (includeArtifacts.isEmpty)
NodeSeq.Empty
else
- NodeSeq.fromSeq(artifacts.flatMap(a => makeDependencyElem(dependency, a)))
+ NodeSeq.fromSeq(artifacts.flatMap(a => makeDependencyElem(dependency, a, excludes)))
}
+ @deprecated("Use `makeDependencyElem` variant which takes excludes", "0.13.9")
def makeDependencyElem(dependency: DependencyDescriptor, artifact: DependencyArtifactDescriptor): Option[Elem] =
+ makeDependencyElem(dependency, artifact, Nil)
+
+ def makeDependencyElem(dependency: DependencyDescriptor, artifact: DependencyArtifactDescriptor, excludes: Seq[ExcludeRule]): Option[Elem] =
{
val configs = artifact.getConfigurations.toList match {
case Nil | "*" :: Nil => dependency.getModuleConfigurations
case x => x.toArray
}
- if (configs.filterNot(Set("sources","docs")).nonEmpty) {
+ if (configs.filterNot(Set("sources", "docs")).nonEmpty) {
val (scope, optional) = getScopeAndOptional(configs)
val classifier = artifactClassifier(artifact)
val baseType = artifactType(artifact)
@@ -258,10 +270,15 @@ class MakePom(val log: Logger) {
case (Some(c), Some(tpe)) if Artifact.classifierType(c) == tpe => None
case _ => baseType
}
- Some(makeDependencyElem(dependency, scope, optional, classifier, tpe))
+ Some(makeDependencyElem(dependency, scope, optional, classifier, tpe, excludes))
} else None
}
+
+ @deprecated("Use `makeDependencyElem` variant which takes excludes", "0.13.9")
def makeDependencyElem(dependency: DependencyDescriptor, scope: Option[String], optional: Boolean, classifier: Option[String], tpe: Option[String]): Elem =
+ makeDependencyElem(dependency, scope, optional, classifier, tpe, Nil)
+
+ def makeDependencyElem(dependency: DependencyDescriptor, scope: Option[String], optional: Boolean, classifier: Option[String], tpe: Option[String], excludes: Seq[ExcludeRule]): Elem =
{
val mrid = dependency.getDependencyRevisionId
@@ -272,7 +289,7 @@ class MakePom(val log: Logger) {
{ optionalElem(optional) }
{ classifierElem(classifier) }
{ typeElem(tpe) }
- { exclusions(dependency) }
+ { exclusions(dependency, excludes) }
}
@@ -322,9 +339,12 @@ class MakePom(val log: Logger) {
(scope, opt.nonEmpty)
}
- def exclusions(dependency: DependencyDescriptor): NodeSeq =
+ @deprecated("Use `exclusions` variant which takes excludes", "0.13.9")
+ def exclusions(dependency: DependencyDescriptor): NodeSeq = exclusions(dependency, Nil)
+
+ def exclusions(dependency: DependencyDescriptor, excludes: Seq[ExcludeRule]): NodeSeq =
{
- val excl = dependency.getExcludeRules(dependency.getModuleConfigurations)
+ val excl = dependency.getExcludeRules(dependency.getModuleConfigurations) ++ excludes
val (warns, excls) = IvyUtil.separate(excl.map(makeExclusion))
if (warns.nonEmpty) log.warn(warns.mkString(IO.Newline))
if (excls.nonEmpty) { excls }
diff --git a/notes/0.13.9/project-level-exclusions-in-the-pom.markdown b/notes/0.13.9/project-level-exclusions-in-the-pom.markdown
new file mode 100644
index 000000000..f534d989e
--- /dev/null
+++ b/notes/0.13.9/project-level-exclusions-in-the-pom.markdown
@@ -0,0 +1,12 @@
+
+ [@dwijnand]: http://github.com/dwijnand
+ [#1877]: https://github.com/sbt/sbt/issues/1877
+ [#2035]: https://github.com/sbt/sbt/pull/2035
+
+### Fixes with compatibility implications
+
+### Improvements
+
+### Bug fixes
+
+- Add dependency-level exclusions in the POM for project-level exclusions. [#1877][]/[#2035][] by [@dwijnand][]
diff --git a/sbt/src/sbt-test/dependency-management/exclude-dependencies/build.sbt b/sbt/src/sbt-test/dependency-management/exclude-dependencies/build.sbt
index 16bc85772..5390886f3 100644
--- a/sbt/src/sbt-test/dependency-management/exclude-dependencies/build.sbt
+++ b/sbt/src/sbt-test/dependency-management/exclude-dependencies/build.sbt
@@ -1,3 +1,6 @@
+import scala.xml.{ Node, _ }
+import scala.xml.Utility.trim
+
lazy val check = taskKey[Unit]("check")
val dispatch = "net.databinder.dispatch" %% "dispatch-core" % "0.11.2"
@@ -31,5 +34,30 @@ lazy val root = (project in file(".")).
if (bcp exists { _.data.getName contains "dispatch-core_2.11-0.11.1.jar" }) {
sys.error("dispatch-core_2.11-0.11.1.jar found when it should NOT be included: " + bcp.toString)
}
+
+ val bPomXml = makePomXml(streams.value.log, (makePomConfiguration in b).value, (ivyModule in b).value)
+
+ val repatchTwitterXml = bPomXml \ "dependencies" \ "dependency" find { d =>
+ (d \ "groupId").text == "com.eed3si9n" && (d \ "artifactId").text == "repatch-twitter-core_2.11"
+ } getOrElse (sys error s"Missing repatch-twitter-core dependency: $bPomXml")
+
+ val excludeDispatchCoreXml =
+
+ net.databinder.dispatch
+ dispatch-core_2.11
+
+
+ if (trim((repatchTwitterXml \ "exclusions" \ "exclusion").head) != trim(excludeDispatchCoreXml))
+ sys error s"Missing dispatch-core exclusion: $repatchTwitterXml"
+
+ ()
}
- )
\ No newline at end of file
+ )
+
+def makePomXml(log: Logger, makePomConfig: MakePomConfiguration, ivyModule: IvySbt#Module): Node = {
+ ivyModule.withModule[Node](log) { (ivy, md, default) =>
+ import makePomConfig._
+ new MakePom(log).toPom(
+ ivy, md, moduleInfo, configurations, includeTypes, extra, filterRepositories, allRepositories)
+ }
+}