Appropriately transfer sbt-plugin transitive 'extra attribute' properties.

* Propogate the extra dependnecy attribute out of pom files into Aether
* Use the extra depednency attributes to ensure transitive plugins can be resolved.
* Add TODOs for further cleanup work.
This commit is contained in:
Josh Suereth 2015-01-09 11:14:27 -05:00
parent beb051879b
commit 095c129eda
4 changed files with 74 additions and 6 deletions

View File

@ -15,7 +15,7 @@ import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorWriter
import org.apache.ivy.plugins.resolver.MavenRepositoryResolver.JarPackaging
import org.apache.ivy.plugins.resolver.util.ResolvedResource
import org.apache.ivy.util.Message
import org.apache.maven.repository.internal.{ SbtRepositoryLayout, SbtExtraProperties }
import org.apache.maven.repository.internal.{ PomExtraDependencyAttributes, SbtRepositoryLayout, SbtExtraProperties }
import org.eclipse.aether.{ RepositorySystemSession, RepositorySystem }
import org.eclipse.aether.artifact.{ DefaultArtifact => AetherArtifact }
import org.eclipse.aether.metadata.{ Metadata, DefaultMetadata }
@ -327,8 +327,7 @@ abstract class AbstractMavenRepositoryResolver(settings: IvySettings) extends Ab
rmr
} catch {
case e: org.eclipse.aether.resolution.ArtifactDescriptorException =>
Message.warn(s"Failed to read descriptor ${dd} from ${getName}, ${e.getMessage}")
e.printStackTrace(System.err)
Message.info(s"Failed to read descriptor ${dd} from ${getName}, ${e.getMessage}")
rd.getCurrentResolvedModuleRevision
case e: MavenResolutionException =>
Message.debug(s"Resolution Exception from ${getName}, ${e.getMessage}, returning: ${rd.getCurrentResolvedModuleRevision}")
@ -456,10 +455,29 @@ abstract class AbstractMavenRepositoryResolver(settings: IvySettings) extends Ab
/** Adds the list of dependencies this artifact has on other artifacts. */
def addDependenciesFromAether(result: AetherDescriptorResult, md: DefaultModuleDescriptor) {
// First we construct a map of any extra attributes we must append to dependencies.
// This is necessary for transitive maven-based sbt plugin dependencies, where we need to
// attach the sbtVersion/scalaVersion to the dependency id otherwise we'll fail to resolve the
// dependency correctly.
val extraAttributes = PomExtraDependencyAttributes.readFromAether(result.getProperties)
for (d <- result.getDependencies.asScala) {
// TODO - Is this correct for changing detection. We should use the Ivy mechanism configured...
val isChanging = d.getArtifact.getVersion.endsWith("-SNAPSHOT")
val drid = ModuleRevisionId.newInstance(d.getArtifact.getGroupId, d.getArtifact.getArtifactId, d.getArtifact.getVersion)
val drid = {
val tmp = ModuleRevisionId.newInstance(d.getArtifact.getGroupId, d.getArtifact.getArtifactId, d.getArtifact.getVersion)
extraAttributes get tmp match {
case Some(props) =>
Message.debug(s"Found $tmp w/ extra attributes ${props.mkString(",")}")
ModuleRevisionId.newInstance(
d.getArtifact.getGroupId,
d.getArtifact.getArtifactId,
d.getArtifact.getVersion,
props.asJava
)
case _ => tmp
}
}
// Note: The previous maven integration ALWAYS set force to true for dependnecies. If we do not do this, for some
// reason, Ivy will create dummy nodes when doing dependnecy mediation (e.g. dependencyManagement of one pom overrides version of a dependency)
// which was leading to "data not found" exceptions as Ivy would pick the correct IvyNode in the dependency tree but never load it with data....

View File

@ -0,0 +1,47 @@
package org.apache.maven.repository.internal
import java.util.Properties
import org.apache.ivy.core.module.id.ModuleRevisionId
import org.apache.ivy.util.extendable.ExtendableItem
import sbt.CustomPomParser
object PomExtraDependencyAttributes {
// TODO - Move custom pom parser extra attribtues code into this class, rather than relying on
// custom pom parser (so we can deprecate it completely).
import CustomPomParser.{ ExtraAttributesKey, simplify, filterCustomExtra, readDependencyExtra }
/**
* Reads the extra dependency attributes out of a maven property.
* @param props The properties from an Aether resolution.
* @return
* A map of module id to extra dependency attributes associated with dependencies on that module.
*/
def readFromAether(props: java.util.Map[String, AnyRef]): Map[ModuleRevisionId, Map[String, String]] = {
import collection.JavaConverters._
(props.asScala get ExtraAttributesKey) match {
case None => Map.empty
case Some(str) =>
def processDep(m: ModuleRevisionId) = (simplify(m), filterCustomExtra(m, include = true))
(for {
(id, props) <- readDependencyExtra(str.toString).map(processDep)
} yield id -> props).toMap
}
}
/**
* Mutates the to collection with the extra depdendency attributes from the incoming pom properties list.
*
* @param from The properties directly off a maven POM file
* @param to The aaether properties where we can write whatever we want.
*
* TODO - maybe we can just parse this directly here. Note the `readFromAether` method uses
* whatever we set here.
*/
def transferDependencyExtraAttributes(from: Properties, to: java.util.Map[String, AnyRef]): Unit = {
Option(from.getProperty(ExtraAttributesKey, null)) match {
case Some(str) => to.put(ExtraAttributesKey, str)
case None =>
}
}
}

View File

@ -228,6 +228,7 @@ public class SbtArtifactDescriptorReader
if ( model != null )
{
ArtifactTypeRegistry stereotypes = session.getArtifactTypeRegistry();
for ( Repository r : model.getRepositories() )
@ -282,7 +283,8 @@ public class SbtArtifactDescriptorReader
properties.put(SbtExtraProperties.SCALA_VERSION_KEY, mprops.getProperty(SbtExtraProperties.POM_SCALA_VERSION));
}
// TODO - Add extra attributes, e.g. sbtVersion + scalaVersion.
// SBT-Added - Here we inject the additional dependency attributes (for transitive plugin resolution).
PomExtraDependencyAttributes.transferDependencyExtraAttributes(model.getProperties(), properties);
result.setProperties( properties);

View File

@ -1,5 +1,7 @@
package org.apache.maven.repository.internal;
/**
* Created by jsuereth on 12/20/14.
*/
@ -19,5 +21,4 @@ public class SbtExtraProperties {
public static String makeLicenseUrl(int i) {
return "license." + i + ".url";
}
}