Support for enhanced cross build suffix in dependencies. Closes #267

Overloading `%%` for library dependency to allow using a library built
with an alternative version of Scala that is different from the Scala
version used in the current build (but hopefully binary compatible).

This is useful in cases, where the binary build of a dependency with
the exact Scala version isn't yet available but an otherwise binary
compatible build (maybe with a previous Scala release) is available.
This commit is contained in:
Indrajit Raychaudhuri 2011-11-16 14:04:16 +05:30
parent a49c907146
commit 0270ac078f
4 changed files with 17 additions and 16 deletions

View File

@ -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)

View File

@ -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

View File

@ -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"))
final class ResolveException(val messages: Seq[String], val failed: Seq[ModuleID]) extends RuntimeException(messages.mkString("\n"))

View File

@ -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)
}
}