From a8fd017499d9e2471157c23fc39f4cf53c4b24f9 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Wed, 27 Jul 2011 19:50:59 -0400 Subject: [PATCH] maven-compatible plugin dependency system --- ivy/CustomPomParser.scala | 88 +++++++++++++++++++++++++++++++++++++++ ivy/Ivy.scala | 7 ++++ ivy/IvyRetrieve.scala | 6 +-- ivy/MakePom.scala | 11 +++++ main/Defaults.scala | 3 +- 5 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 ivy/CustomPomParser.scala diff --git a/ivy/CustomPomParser.scala b/ivy/CustomPomParser.scala new file mode 100644 index 000000000..c2c928a6f --- /dev/null +++ b/ivy/CustomPomParser.scala @@ -0,0 +1,88 @@ +package sbt + + import org.apache.ivy.{core, plugins} + import core.module.id.ModuleRevisionId + import core.module.descriptor.{DefaultArtifact, DefaultExtendsDescriptor, DefaultModuleDescriptor, ModuleDescriptor} + import plugins.parser.{m2, ModuleDescriptorParser, ModuleDescriptorParserRegistry, ParserSettings} + import m2.{PomModuleDescriptorBuilder, PomModuleDescriptorParser} + import plugins.repository.Resource + + import java.io.{File, InputStream} + import java.net.URL + +final class CustomPomParser(delegate: ModuleDescriptorParser, transform: (ModuleDescriptorParser, ModuleDescriptor) => ModuleDescriptor) extends ModuleDescriptorParser +{ + override def parseDescriptor(ivySettings: ParserSettings, descriptorURL: URL, validate: Boolean) = + transform(this, delegate.parseDescriptor(ivySettings, descriptorURL, validate)) + + override def parseDescriptor(ivySettings: ParserSettings, descriptorURL: URL, res: Resource, validate: Boolean) = + transform(this, delegate.parseDescriptor(ivySettings, descriptorURL, res, validate)) + + override def toIvyFile(is: InputStream, res: Resource, destFile: File, md: ModuleDescriptor) = delegate.toIvyFile(is, res, destFile, md) + + override def accept(res: Resource) = delegate.accept(res) + override def getType() = delegate.getType() + override def getMetadataArtifact(mrid: ModuleRevisionId, res: Resource) = delegate.getMetadataArtifact(mrid, res) +} +object CustomPomParser +{ + val SbtVersionKey = "sbtVersion" + val ScalaVersionKey = "scalaVersion" + + val default = new CustomPomParser(PomModuleDescriptorParser.getInstance, defaultTransform) + + // Unfortunately, ModuleDescriptorParserRegistry is add-only and is a singleton instance. + lazy val registerDefault: Unit = ModuleDescriptorParserRegistry.getInstance.addParser(default) + + def defaultTransform(parser: ModuleDescriptorParser, md: ModuleDescriptor): ModuleDescriptor = + { + import collection.JavaConverters._ + val properties = PomModuleDescriptorBuilder.extractPomProperties(md.getExtraInfo).asInstanceOf[java.util.Map[String,String]].asScala.toMap + val filtered = shouldBeUnqualified(properties) + if(filtered.isEmpty) md else addExtra(filtered, parser, md) + } + private[this] def shouldBeUnqualified(m: Map[String, String]): Map[String, String] = + m.filter { case (k,_) => k == SbtVersionKey || k == ScalaVersionKey } + + private[this] def addExtra(properties: Map[String, String], id: ModuleRevisionId): ModuleRevisionId = + { + import collection.JavaConverters._ + val oldExtra = id.getQualifiedExtraAttributes.asInstanceOf[java.util.Map[String,String]].asScala + val newExtra = (oldExtra ++ properties).asJava + ModuleRevisionId.newInstance(id.getOrganisation, id.getName, id.getBranch, id.getRevision, newExtra) + } + + import collection.JavaConverters._ + def addExtra(properties: Map[String, String], parser: ModuleDescriptorParser, md: ModuleDescriptor): ModuleDescriptor = + { + val dmd = new DefaultModuleDescriptor(parser, md.getResource) + + val mrid = addExtra(properties, md.getModuleRevisionId) + val resolvedMrid = addExtra(properties, md.getResolvedModuleRevisionId) + dmd.setModuleRevisionId(mrid) + dmd.setResolvedModuleRevisionId(resolvedMrid) + + dmd.setDefault(md.isDefault) + dmd.setHomePage(md.getHomePage) + dmd.setDescription(md.getDescription) + dmd.setLastModified(md.getLastModified) + dmd.setStatus(md.getStatus()) + dmd.setPublicationDate(md.getPublicationDate()) + dmd.setResolvedPublicationDate(md.getResolvedPublicationDate()) + + for(l <- md.getLicenses) dmd.addLicense(l) + 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( dd <- md.getDependencies ) dmd.addDependency(dd) + + for( ed <- md.getInheritedDescriptors) dmd.addInheritedDescriptor( new DefaultExtendsDescriptor( mrid, resolvedMrid, ed.getLocation, ed.getExtendsTypes) ) + for( conf <- md.getConfigurations) { + dmd.addConfiguration(conf) + for(art <- md.getArtifacts(conf.getName)) { + val nart = new DefaultArtifact(mrid, art.getPublicationDate, art.getName, art.getType, art.getExt, art.getUrl, art.getQualifiedExtraAttributes) + dmd.addArtifact(conf.getName, nart) + } + } + dmd + } +} \ No newline at end of file diff --git a/ivy/Ivy.scala b/ivy/Ivy.scala index d461f1f18..89aa46592 100644 --- a/ivy/Ivy.scala +++ b/ivy/Ivy.scala @@ -25,6 +25,7 @@ import plugins.matcher.PatternMatcher import plugins.parser.m2.PomModuleDescriptorParser import plugins.resolver.{ChainResolver, DependencyResolver} import util.{Message, MessageLogger} +import util.extendable.ExtendableItem import scala.xml.NodeSeq @@ -61,6 +62,7 @@ final class IvySbt(val configuration: IvyConfiguration) { val is = new IvySettings is.setBaseDir(baseDirectory) + CustomPomParser.registerDefault configuration match { case e: ExternalIvyConfiguration => is.load(e.file) @@ -319,6 +321,11 @@ private object IvySbt configurations.foreach(artifact.addConfiguration) artifact } + def getExtraAttributes(revID: ExtendableItem): Map[String,String] = + { + import collection.JavaConverters._ + revID.getExtraAttributes.asInstanceOf[java.util.Map[String,String]].asScala.toMap + } private[sbt] def extra(artifact: Artifact, unqualify: Boolean = false): java.util.Map[String, String] = { val ea = artifact.classifier match { case Some(c) => artifact.extra("e:classifier" -> c); case None => artifact } diff --git a/ivy/IvyRetrieve.scala b/ivy/IvyRetrieve.scala index c36703c2f..7c96c63ff 100644 --- a/ivy/IvyRetrieve.scala +++ b/ivy/IvyRetrieve.scala @@ -39,11 +39,7 @@ object IvyRetrieve confReport.getEvictedNodes.map(node => toModuleID(node.getId)) def toModuleID(revID: ModuleRevisionId): ModuleID = - { - import collection.JavaConverters._ - val extra = revID.getExtraAttributes.asInstanceOf[java.util.Map[String,String]].asScala - ModuleID(revID.getOrganisation, revID.getName, revID.getRevision, extraAttributes = extra.toMap) - } + ModuleID(revID.getOrganisation, revID.getName, revID.getRevision, extraAttributes = IvySbt.getExtraAttributes(revID)) def toArtifact(art: IvyArtifact): Artifact = { diff --git a/ivy/MakePom.scala b/ivy/MakePom.scala index 432a83ba6..063b44e5b 100644 --- a/ivy/MakePom.scala +++ b/ivy/MakePom.scala @@ -42,6 +42,7 @@ class MakePom 4.0.0 { makeModuleID(module) } { extra } + { makeProperties(module) } { makeDependencies(module, configurations) } { makeRepositories(ivy.getSettings, allRepositories, filterRepositories) } ) @@ -60,6 +61,16 @@ class MakePom licenses(module.getLicenses)) : NodeSeq ) a ++ b } + def makeProperties(module: ModuleDescriptor): NodeSeq = + { + val extra = IvySbt.getExtraAttributes(module) + if(extra.isEmpty) NodeSeq.Empty else makeProperties(extra) + } + def makeProperties(extra: Map[String,String]): NodeSeq = + { + for( (key,value) <- extra ) yield + ({value}).copy(label = key) + } def description(d: String) = if((d eq null) || d.isEmpty) NodeSeq.Empty else {d} def licenses(ls: Array[License]) = if(ls == null || ls.isEmpty) NodeSeq.Empty else {ls.map(license)} diff --git a/main/Defaults.scala b/main/Defaults.scala index 5628eb9b0..e03267d1e 100644 --- a/main/Defaults.scala +++ b/main/Defaults.scala @@ -433,7 +433,7 @@ object Defaults extends BuildCommon Compiler.inputs(classpath, srcs, classes, scalacOpts, javacOpts, 100, order)(cs, incSetup, s.log) } - def sbtPluginExtra(m: ModuleID, sbtV: String, scalaV: String): ModuleID = m.extra("e:sbtVersion" -> sbtV, "e:scalaVersion" -> scalaV).copy(crossVersion = false) + def sbtPluginExtra(m: ModuleID, sbtV: String, scalaV: String): ModuleID = m.extra(CustomPomParser.SbtVersionKey -> sbtV, CustomPomParser.ScalaVersionKey -> scalaV).copy(crossVersion = false) def writePluginsDescriptor(plugins: Set[String], dir: File): List[File] = { val descriptor: File = dir / "sbt" / "sbt.plugins" @@ -605,7 +605,6 @@ object Classpaths otherResolvers <<= publishTo(_.toList), projectResolver <<= projectResolverTask, projectDependencies <<= projectDependenciesTask, - publishMavenStyle <<= (publishMavenStyle, sbtPlugin) { (style, plugin) => style && !plugin }, libraryDependencies in GlobalScope :== Nil, libraryDependencies <++= (autoScalaLibrary, sbtPlugin, scalaVersion) apply autoLibraryDependency, allDependencies <<= (projectDependencies,libraryDependencies,sbtPlugin,sbtDependency) map { (projDeps, libDeps, isPlugin, sbtDep) =>