diff --git a/ivy/DependencyBuilders.scala b/ivy/DependencyBuilders.scala index 00168d7c1..68a30b122 100644 --- a/ivy/DependencyBuilders.scala +++ b/ivy/DependencyBuilders.scala @@ -4,7 +4,7 @@ package sbt package impl - import StringUtilities.{appendable,nonEmpty} +import StringUtilities.nonEmpty trait DependencyBuilders { @@ -27,20 +27,21 @@ trait DependencyBuilders final class GroupID private[sbt] (groupID: String) { - def % (artifactID: String) = groupArtifact(artifactID, false) - def %% (artifactID: String) = groupArtifact(artifactID, true) - private def groupArtifact(artifactID: String, cross: Boolean) = + def % (artifactID: String) = groupArtifact(artifactID, None) + def %% (artifactID: String, crossVersion: String => String = identity) = groupArtifact(artifactID, Some(crossVersion)) + def %% (artifactID: String, alternatives: (String, String)*) = groupArtifact(artifactID, Some(Map(alternatives: _*) orElse { case s => s })) + private def groupArtifact(artifactID: String, cross: Option[String => String]) = { nonEmpty(artifactID, "Artifact ID") new GroupArtifactID(groupID, artifactID, cross) } } -final class GroupArtifactID private[sbt] (groupID: String, artifactID: String, crossVersion: Boolean) -{ +final class GroupArtifactID private[sbt] (groupID: String, artifactID: String, crossVersion: Option[String => String]) +{ def % (revision: String): ModuleID = { nonEmpty(revision, "Revision") - ModuleID(groupID, artifactID, revision).cross(crossVersion) + ModuleID(groupID, artifactID, revision).cross(!crossVersion.isEmpty, crossVersion.getOrElse(identity)) } } final class ModuleIDConfigurable private[sbt] (moduleID: ModuleID) diff --git a/ivy/Ivy.scala b/ivy/Ivy.scala index 3cac60e0b..19252fb28 100644 --- a/ivy/Ivy.scala +++ b/ivy/Ivy.scala @@ -314,7 +314,7 @@ private object IvySbt as.map(art => substituteCross(art, cross)) def substituteCross(m: ModuleID, cross: String): ModuleID = if(m.crossVersion) - m.copy(name = crossName(m.name, cross), explicitArtifacts = substituteCrossA(m.explicitArtifacts, cross)) + m.copy(name = crossName(m.name, m.crossVersionRemap(cross)), explicitArtifacts = substituteCrossA(m.explicitArtifacts, cross)) else m diff --git a/ivy/IvyActions.scala b/ivy/IvyActions.scala index ff53041ef..07b2740d1 100644 --- a/ivy/IvyActions.scala +++ b/ivy/IvyActions.scala @@ -205,7 +205,7 @@ object IvyActions report.allMissing flatMap { case (_, mod, art) => art.classifier.map { c => (restrictedCopy(mod, false), c) } } groupBy(_._1) map { case (mod, pairs) => (mod, pairs.map(_._2).toSet) } private[this] def restrictedCopy(m: ModuleID, confs: Boolean) = - ModuleID(m.organization, m.name, m.revision, crossVersion = m.crossVersion, extraAttributes = m.extraAttributes, configurations = if(confs) m.configurations else None) + ModuleID(m.organization, m.name, m.revision, crossVersion = m.crossVersion, crossVersionRemap = m.crossVersionRemap, extraAttributes = m.extraAttributes, configurations = if(confs) m.configurations else None) private[this] def resolve(logging: UpdateLogging.Value)(ivy: Ivy, module: DefaultModuleDescriptor, defaultConf: String): (ResolveReport, Option[ResolveException]) = { val resolveOptions = new ResolveOptions @@ -268,4 +268,4 @@ object IvyActions } } -final class ResolveException(val messages: Seq[String], val failed: Seq[ModuleID]) extends RuntimeException(messages.mkString("\n")) \ No newline at end of file +final class ResolveException(val messages: Seq[String], val failed: Seq[ModuleID]) extends RuntimeException(messages.mkString("\n")) diff --git a/ivy/IvyInterface.scala b/ivy/IvyInterface.scala index 9f5b0c630..7bf72b0dc 100644 --- a/ivy/IvyInterface.scala +++ b/ivy/IvyInterface.scala @@ -9,14 +9,14 @@ import scala.xml.NodeSeq import org.apache.ivy.plugins.resolver.{DependencyResolver, IBiblioResolver} import org.apache.ivy.util.url.CredentialsStore -final case class ModuleID(organization: String, name: String, revision: String, configurations: Option[String] = None, isChanging: Boolean = false, isTransitive: Boolean = true, explicitArtifacts: Seq[Artifact] = Nil, exclusions: Seq[ExclusionRule] = Nil, extraAttributes: Map[String,String] = Map.empty, crossVersion: Boolean = false) +final case class ModuleID(organization: String, name: String, revision: String, configurations: Option[String] = None, isChanging: Boolean = false, isTransitive: Boolean = true, explicitArtifacts: Seq[Artifact] = Nil, exclusions: Seq[ExclusionRule] = Nil, extraAttributes: Map[String,String] = Map.empty, crossVersion: Boolean = false, crossVersionRemap: String => String = identity) { override def toString = organization + ":" + name + ":" + revision + (configurations match { case Some(s) => ":" + s; case None => "" }) + (if(extraAttributes.isEmpty) "" else " " + extraString) def extraString = extraAttributes.map { case (k,v) => k + "=" + v } mkString("(",", ",")") - def cross(v: Boolean) = copy(crossVersion = v) + def cross(v: Boolean, verRemap: String => String = identity) = copy(crossVersion = v, crossVersionRemap = verRemap) // () required for chaining def notTransitive() = intransitive() def intransitive() = copy(isTransitive = false) @@ -282,7 +282,7 @@ object Resolver def resolveAll(patterns: Seq[String]) = patterns.map(p => resolvePattern(base, p)) Patterns(resolveAll(basePatterns.ivyPatterns), resolveAll(basePatterns.artifactPatterns), basePatterns.isMavenCompatible) } - private[sbt] def resolvePattern(base: String, pattern: String): String = + private[sbt] def resolvePattern(base: String, pattern: String): String = { val normBase = base.replace('\\', '/') if(normBase.endsWith("/") || pattern.startsWith("/")) normBase + pattern else normBase + "/" + pattern @@ -423,14 +423,14 @@ object Artifact { import artifact._ val classifierStr = classifier match { case None => ""; case Some(c) => "-" + c } - val base = if(module.crossVersion) IvySbt.crossName(artifact.name, scalaVersion) else artifact.name + val base = if(module.crossVersion) IvySbt.crossName(artifact.name, module.crossVersionRemap(scalaVersion)) else artifact.name base + "-" + module.revision + classifierStr + "." + artifact.extension } def cross(enable: Boolean, scalaVersion: String): String = if(enable) "_" + scalaVersion else "" val classifierConfMap = Map(SourceClassifier -> Sources, DocClassifier -> Docs) val classifierTypeMap = Map(SourceClassifier -> SourceType, DocClassifier -> DocType) - def classifierConf(classifier: String): Configuration = classifierConfMap.getOrElse(classifier, Optional) + def classifierConf(classifier: String): Configuration = classifierConfMap.getOrElse(classifier, Optional) def classifierType(classifier: String): String = classifierTypeMap.getOrElse(classifier, DefaultType) def classified(name: String, classifier: String): Artifact = Artifact(name, classifierType(classifier), DefaultExtension, Some(classifier), classifierConf(classifier) :: Nil, None) @@ -440,4 +440,4 @@ 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) -} \ No newline at end of file +}