mirror of https://github.com/sbt/sbt.git
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:
parent
a49c907146
commit
0270ac078f
|
|
@ -4,7 +4,7 @@
|
||||||
package sbt
|
package sbt
|
||||||
package impl
|
package impl
|
||||||
|
|
||||||
import StringUtilities.{appendable,nonEmpty}
|
import StringUtilities.nonEmpty
|
||||||
|
|
||||||
trait DependencyBuilders
|
trait DependencyBuilders
|
||||||
{
|
{
|
||||||
|
|
@ -27,20 +27,21 @@ trait DependencyBuilders
|
||||||
|
|
||||||
final class GroupID private[sbt] (groupID: String)
|
final class GroupID private[sbt] (groupID: String)
|
||||||
{
|
{
|
||||||
def % (artifactID: String) = groupArtifact(artifactID, false)
|
def % (artifactID: String) = groupArtifact(artifactID, None)
|
||||||
def %% (artifactID: String) = groupArtifact(artifactID, true)
|
def %% (artifactID: String, crossVersion: String => String = identity) = groupArtifact(artifactID, Some(crossVersion))
|
||||||
private def groupArtifact(artifactID: String, cross: Boolean) =
|
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")
|
nonEmpty(artifactID, "Artifact ID")
|
||||||
new GroupArtifactID(groupID, artifactID, cross)
|
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 =
|
def % (revision: String): ModuleID =
|
||||||
{
|
{
|
||||||
nonEmpty(revision, "Revision")
|
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)
|
final class ModuleIDConfigurable private[sbt] (moduleID: ModuleID)
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,7 @@ private object IvySbt
|
||||||
as.map(art => substituteCross(art, cross))
|
as.map(art => substituteCross(art, cross))
|
||||||
def substituteCross(m: ModuleID, cross: String): ModuleID =
|
def substituteCross(m: ModuleID, cross: String): ModuleID =
|
||||||
if(m.crossVersion)
|
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
|
else
|
||||||
m
|
m
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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) }
|
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) =
|
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]) =
|
private[this] def resolve(logging: UpdateLogging.Value)(ivy: Ivy, module: DefaultModuleDescriptor, defaultConf: String): (ResolveReport, Option[ResolveException]) =
|
||||||
{
|
{
|
||||||
val resolveOptions = new ResolveOptions
|
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"))
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,14 @@ import scala.xml.NodeSeq
|
||||||
import org.apache.ivy.plugins.resolver.{DependencyResolver, IBiblioResolver}
|
import org.apache.ivy.plugins.resolver.{DependencyResolver, IBiblioResolver}
|
||||||
import org.apache.ivy.util.url.CredentialsStore
|
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 =
|
override def toString =
|
||||||
organization + ":" + name + ":" + revision +
|
organization + ":" + name + ":" + revision +
|
||||||
(configurations match { case Some(s) => ":" + s; case None => "" }) +
|
(configurations match { case Some(s) => ":" + s; case None => "" }) +
|
||||||
(if(extraAttributes.isEmpty) "" else " " + extraString)
|
(if(extraAttributes.isEmpty) "" else " " + extraString)
|
||||||
def extraString = extraAttributes.map { case (k,v) => k + "=" + v } mkString("(",", ",")")
|
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
|
// () required for chaining
|
||||||
def notTransitive() = intransitive()
|
def notTransitive() = intransitive()
|
||||||
def intransitive() = copy(isTransitive = false)
|
def intransitive() = copy(isTransitive = false)
|
||||||
|
|
@ -282,7 +282,7 @@ object Resolver
|
||||||
def resolveAll(patterns: Seq[String]) = patterns.map(p => resolvePattern(base, p))
|
def resolveAll(patterns: Seq[String]) = patterns.map(p => resolvePattern(base, p))
|
||||||
Patterns(resolveAll(basePatterns.ivyPatterns), resolveAll(basePatterns.artifactPatterns), basePatterns.isMavenCompatible)
|
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('\\', '/')
|
val normBase = base.replace('\\', '/')
|
||||||
if(normBase.endsWith("/") || pattern.startsWith("/")) normBase + pattern else normBase + "/" + pattern
|
if(normBase.endsWith("/") || pattern.startsWith("/")) normBase + pattern else normBase + "/" + pattern
|
||||||
|
|
@ -423,14 +423,14 @@ object Artifact
|
||||||
{
|
{
|
||||||
import artifact._
|
import artifact._
|
||||||
val classifierStr = classifier match { case None => ""; case Some(c) => "-" + c }
|
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
|
base + "-" + module.revision + classifierStr + "." + artifact.extension
|
||||||
}
|
}
|
||||||
def cross(enable: Boolean, scalaVersion: String): String = if(enable) "_" + scalaVersion else ""
|
def cross(enable: Boolean, scalaVersion: String): String = if(enable) "_" + scalaVersion else ""
|
||||||
|
|
||||||
val classifierConfMap = Map(SourceClassifier -> Sources, DocClassifier -> Docs)
|
val classifierConfMap = Map(SourceClassifier -> Sources, DocClassifier -> Docs)
|
||||||
val classifierTypeMap = Map(SourceClassifier -> SourceType, DocClassifier -> DocType)
|
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 classifierType(classifier: String): String = classifierTypeMap.getOrElse(classifier, DefaultType)
|
||||||
def classified(name: String, classifier: String): Artifact =
|
def classified(name: String, classifier: String): Artifact =
|
||||||
Artifact(name, classifierType(classifier), DefaultExtension, Some(classifier), classifierConf(classifier) :: Nil, None)
|
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, resolver: Resolver): ModuleConfiguration = apply(org, "*", "*", resolver)
|
||||||
def apply(org: String, name: String, resolver: Resolver): ModuleConfiguration = ModuleConfiguration(org, name, "*", resolver)
|
def apply(org: String, name: String, resolver: Resolver): ModuleConfiguration = ModuleConfiguration(org, name, "*", resolver)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue