Merge pull request #1748 from sbt/wip/1748

excludeDependencies: excludeAll at the project level
This commit is contained in:
Josh Suereth 2014-12-05 09:06:09 -05:00
commit bbe3ebf940
7 changed files with 157 additions and 22 deletions

View File

@ -96,6 +96,13 @@ object CrossVersion {
def crossName(name: String, cross: String): String =
name + "_" + cross
/** Cross-versions `exclude` according to its `crossVersion`. */
private[sbt] def substituteCross(exclude: SbtExclusionRule, is: Option[IvyScala]): SbtExclusionRule = {
val fopt: Option[String => String] =
is flatMap { i => CrossVersion(exclude.crossVersion, i.scalaFullVersion, i.scalaBinaryVersion) }
exclude.copy(name = applyCross(exclude.name, fopt))
}
/** Cross-versions `a` according to cross-version function `cross`. */
def substituteCross(a: Artifact, cross: Option[String => String]): Artifact =
a.copy(name = applyCross(a.name, cross))

View File

@ -137,8 +137,9 @@ object EvictionWarning {
private[sbt] def processEvictions(module: IvySbt#Module, options: EvictionWarningOptions, reports: Seq[OrganizationArtifactReport]): EvictionWarning = {
val directDependencies = module.moduleSettings match {
case x: InlineConfiguration => x.dependencies
case _ => Seq()
case x: InlineConfiguration => x.dependencies
case x: InlineConfigurationWithExcludes => x.dependencies
case _ => Seq()
}
val pairs = reports map { detail =>
val evicteds = detail.modules filter { _.evicted }

View File

@ -163,16 +163,17 @@ final class IvySbt(val configuration: IvyConfiguration) {
{
val (baseModule, baseConfiguration) =
moduleSettings match {
case ic: InlineConfiguration => configureInline(ic, configuration.log)
case ec: EmptyConfiguration => configureEmpty(ec)
case pc: PomConfiguration => configurePom(pc)
case ifc: IvyFileConfiguration => configureIvyFile(ifc)
case ic: InlineConfiguration => configureInline(ic.withExcludes, configuration.log)
case ic: InlineConfigurationWithExcludes => configureInline(ic, configuration.log)
case ec: EmptyConfiguration => configureEmpty(ec)
case pc: PomConfiguration => configurePom(pc)
case ifc: IvyFileConfiguration => configureIvyFile(ifc)
}
moduleSettings.ivyScala.foreach(IvyScala.checkModule(baseModule, baseConfiguration, configuration.log))
IvySbt.addExtraNamespace(baseModule)
(baseModule, baseConfiguration)
}
private def configureInline(ic: InlineConfiguration, log: Logger) =
private def configureInline(ic: InlineConfigurationWithExcludes, log: Logger) =
{
import ic._
val moduleID = newConfiguredModuleID(module, moduleInfo, configurations)
@ -183,6 +184,7 @@ final class IvySbt(val configuration: IvyConfiguration) {
val parser = IvySbt.parseIvyXML(ivy.getSettings, IvySbt.wrapped(module, ivyXML), moduleID, defaultConf.name, validate)
IvySbt.addMainArtifact(moduleID)
IvySbt.addOverrides(moduleID, overrides, ivy.getSettings.getMatcher(PatternMatcher.EXACT))
IvySbt.addExcludes(moduleID, excludes, ivyScala)
val transformedDeps = IvySbt.overrideDirect(dependencies, overrides)
IvySbt.addDependencies(moduleID, transformedDeps, parser)
(moduleID, parser.getDefaultConf)
@ -433,9 +435,10 @@ private[sbt] object IvySbt {
{
val sub = CrossVersion(scalaFullVersion, scalaBinaryVersion)
m match {
case ec: EmptyConfiguration => ec.copy(module = sub(ec.module))
case ic: InlineConfiguration => ic.copy(module = sub(ic.module), dependencies = ic.dependencies map sub, overrides = ic.overrides map sub)
case _ => m
case ec: EmptyConfiguration => ec.copy(module = sub(ec.module))
case ic: InlineConfiguration => ic.copy(module = sub(ic.module), dependencies = ic.dependencies map sub, overrides = ic.overrides map sub)
case ic: InlineConfigurationWithExcludes => ic.copy(module = sub(ic.module), dependencies = ic.dependencies map sub, overrides = ic.overrides map sub)
case _ => m
}
}
@ -603,6 +606,19 @@ private[sbt] object IvySbt {
confs foreach addConfiguration
}
def addExcludes(moduleID: DefaultModuleDescriptor, excludes: Seq[SbtExclusionRule], ivyScala: Option[IvyScala]): Unit =
excludes foreach addExclude(moduleID, ivyScala)
def addExclude(moduleID: DefaultModuleDescriptor, ivyScala: Option[IvyScala])(exclude0: SbtExclusionRule): Unit =
{
// this adds _2.11 postfix
val exclude = CrossVersion.substituteCross(exclude0, ivyScala)
val confs =
if (exclude.configurations.isEmpty) moduleID.getConfigurationsNames.toList
else exclude.configurations
val excludeRule = IvyScala.excludeRule(exclude.organization, exclude.name, confs, exclude.artifact)
moduleID.addExcludeRule(excludeRule)
}
def addOverrides(moduleID: DefaultModuleDescriptor, overrides: Set[ModuleID], matcher: PatternMatcher): Unit =
overrides foreach addOverride(moduleID, matcher)
def addOverride(moduleID: DefaultModuleDescriptor, matcher: PatternMatcher)(overrideDef: ModuleID): Unit =

View File

@ -132,9 +132,10 @@ object IvyActions {
}
private def crossVersionMap(moduleSettings: ModuleSettings): Option[String => String] =
moduleSettings match {
case i: InlineConfiguration => CrossVersion(i.module, i.ivyScala)
case e: EmptyConfiguration => CrossVersion(e.module, e.ivyScala)
case _ => None
case i: InlineConfiguration => CrossVersion(i.module, i.ivyScala)
case i: InlineConfigurationWithExcludes => CrossVersion(i.module, i.ivyScala)
case e: EmptyConfiguration => CrossVersion(e.module, e.ivyScala)
case _ => None
}
def mapArtifacts(module: ModuleDescriptor, cross: Option[String => String], artifacts: Map[Artifact, File]): Seq[(IArtifact, File)] =
{
@ -216,7 +217,7 @@ object IvyActions {
import config.{ configuration => c, ivyScala, module => mod }
import mod.{ id, modules => deps }
val base = restrictedCopy(id, true).copy(name = id.name + "$" + label)
val module = new ivySbt.Module(InlineConfiguration(base, ModuleInfo(base.name), deps).copy(ivyScala = ivyScala))
val module = new ivySbt.Module(InlineConfigurationWithExcludes(base, ModuleInfo(base.name), deps).copy(ivyScala = ivyScala))
val report = updateEither(module, c, uwconfig, logicalClock, depDir, log) match {
case Right(r) => r
case Left(w) =>
@ -238,7 +239,7 @@ object IvyActions {
val baseModules = modules map { m => restrictedCopy(m, true) }
val deps = baseModules.distinct flatMap classifiedArtifacts(classifiers, exclude)
val base = restrictedCopy(id, true).copy(name = id.name + classifiers.mkString("$", "_", ""))
val module = new ivySbt.Module(InlineConfiguration(base, ModuleInfo(base.name), deps).copy(ivyScala = ivyScala, configurations = confs))
val module = new ivySbt.Module(InlineConfigurationWithExcludes(base, ModuleInfo(base.name), deps).copy(ivyScala = ivyScala, configurations = confs))
val upConf = new UpdateConfiguration(c.retrieve, true, c.logging)
updateEither(module, upConf, uwconfig, logicalClock, depDir, log) match {
case Right(r) => r

View File

@ -82,15 +82,18 @@ final case class IvyFileConfiguration(file: File, ivyScala: Option[IvyScala], va
final case class PomConfiguration(file: File, ivyScala: Option[IvyScala], validate: Boolean, autoScalaTools: Boolean = true) extends ModuleSettings {
def noScala = copy(ivyScala = None)
}
// TODO: When we go sbt 1.0 we should rename InlineConfigurationWithExcludes to InlineConfiguration.
@deprecated("Use InlineConfigurationWithExcludes.", "0.13.8")
final case class InlineConfiguration(module: ModuleID, moduleInfo: ModuleInfo, dependencies: Seq[ModuleID], overrides: Set[ModuleID] = Set.empty, ivyXML: NodeSeq = NodeSeq.Empty, configurations: Seq[Configuration] = Nil, defaultConfiguration: Option[Configuration] = None, ivyScala: Option[IvyScala] = None, validate: Boolean = false, conflictManager: ConflictManager = ConflictManager.default) extends ModuleSettings {
def withConfigurations(configurations: Seq[Configuration]) = copy(configurations = configurations)
def noScala = copy(ivyScala = None)
}
@deprecated("Define a module using inline Scala (InlineConfiguration), a pom.xml (PomConfiguration), or an ivy.xml (IvyFileConfiguration).", "0.13.0")
final case class EmptyConfiguration(module: ModuleID, moduleInfo: ModuleInfo, ivyScala: Option[IvyScala], validate: Boolean) extends ModuleSettings {
def noScala = copy(ivyScala = None)
def withExcludes: InlineConfigurationWithExcludes =
InlineConfigurationWithExcludes(this.module, this.moduleInfo, this.dependencies, this.overrides, Nil, this.ivyXML,
this.configurations, this.defaultConfiguration, this.ivyScala, this.validate, this.conflictManager)
}
object InlineConfiguration {
@deprecated("Use InlineConfigurationWithExcludes.explicitConfigurations.", "0.13.8")
def configurations(explicitConfigurations: Iterable[Configuration], defaultConfiguration: Option[Configuration]) =
if (explicitConfigurations.isEmpty) {
defaultConfiguration match {
@ -101,6 +104,67 @@ object InlineConfiguration {
} else
explicitConfigurations
}
final class InlineConfigurationWithExcludes private[sbt] (val module: ModuleID,
val moduleInfo: ModuleInfo,
val dependencies: Seq[ModuleID],
val overrides: Set[ModuleID] = Set.empty,
val excludes: Seq[SbtExclusionRule],
val ivyXML: NodeSeq = NodeSeq.Empty,
val configurations: Seq[Configuration] = Nil,
val defaultConfiguration: Option[Configuration] = None,
val ivyScala: Option[IvyScala] = None,
val validate: Boolean = false,
val conflictManager: ConflictManager = ConflictManager.default) extends ModuleSettings {
def withConfigurations(configurations: Seq[Configuration]) = copy(configurations = configurations)
def noScala = copy(ivyScala = None)
def copy(module: ModuleID = this.module,
moduleInfo: ModuleInfo = this.moduleInfo,
dependencies: Seq[ModuleID] = this.dependencies,
overrides: Set[ModuleID] = this.overrides,
excludes: Seq[SbtExclusionRule] = this.excludes,
ivyXML: NodeSeq = this.ivyXML,
configurations: Seq[Configuration] = this.configurations,
defaultConfiguration: Option[Configuration] = this.defaultConfiguration,
ivyScala: Option[IvyScala] = this.ivyScala,
validate: Boolean = this.validate,
conflictManager: ConflictManager = this.conflictManager): InlineConfigurationWithExcludes =
InlineConfigurationWithExcludes(module, moduleInfo, dependencies, overrides, excludes, ivyXML,
configurations, defaultConfiguration, ivyScala, validate, conflictManager)
}
object InlineConfigurationWithExcludes {
def apply(module: ModuleID,
moduleInfo: ModuleInfo,
dependencies: Seq[ModuleID],
overrides: Set[ModuleID] = Set.empty,
excludes: Seq[SbtExclusionRule] = Nil,
ivyXML: NodeSeq = NodeSeq.Empty,
configurations: Seq[Configuration] = Nil,
defaultConfiguration: Option[Configuration] = None,
ivyScala: Option[IvyScala] = None,
validate: Boolean = false,
conflictManager: ConflictManager = ConflictManager.default): InlineConfigurationWithExcludes =
new InlineConfigurationWithExcludes(module, moduleInfo, dependencies, overrides, excludes, ivyXML,
configurations, defaultConfiguration, ivyScala, validate, conflictManager)
def configurations(explicitConfigurations: Iterable[Configuration], defaultConfiguration: Option[Configuration]) =
if (explicitConfigurations.isEmpty) {
defaultConfiguration match {
case Some(Configurations.DefaultIvyConfiguration) => Configurations.Default :: Nil
case Some(Configurations.DefaultMavenConfiguration) => Configurations.defaultMavenConfigurations
case _ => Nil
}
} else
explicitConfigurations
}
@deprecated("Define a module using inline Scala (InlineConfiguration), a pom.xml (PomConfiguration), or an ivy.xml (IvyFileConfiguration).", "0.13.0")
final case class EmptyConfiguration(module: ModuleID, moduleInfo: ModuleInfo, ivyScala: Option[IvyScala], validate: Boolean) extends ModuleSettings {
def noScala = copy(ivyScala = None)
}
object ModuleSettings {
@deprecated("Explicitly select configuration from pom.xml, ivy.xml, or inline Scala.", "0.13.0")
def apply(ivyScala: Option[IvyScala], validate: Boolean, module: => ModuleID, moduleInfo: => ModuleInfo)(baseDirectory: File, log: Logger): ModuleSettings =

View File

@ -0,0 +1,44 @@
package sbt
import sbt.impl.{ GroupID, GroupArtifactID }
final class SbtExclusionRule(
val organization: String,
val name: String,
val artifact: String,
val configurations: Seq[String],
val crossVersion: CrossVersion) {
def copy(organization: String = this.organization,
name: String = this.name,
artifact: String = this.artifact,
configurations: Seq[String] = this.configurations,
crossVersion: CrossVersion = this.crossVersion): SbtExclusionRule =
SbtExclusionRule(organization = organization,
name = name,
artifact = artifact,
configurations = configurations,
crossVersion = crossVersion)
}
object SbtExclusionRule {
def apply(organization: String): SbtExclusionRule =
new SbtExclusionRule(organization, "*", "*", Nil, CrossVersion.Disabled)
def apply(organization: String, name: String): SbtExclusionRule =
new SbtExclusionRule(organization, name, "*", Nil, CrossVersion.Disabled)
def apply(organization: String,
name: String,
artifact: String,
configurations: Seq[String],
crossVersion: CrossVersion): SbtExclusionRule =
new SbtExclusionRule(organization, name, artifact, configurations, crossVersion)
implicit def groupIdToExclusionRule(organization: GroupID): SbtExclusionRule =
SbtExclusionRule(organization.groupID)
implicit def stringToExclusionRule(organization: String): SbtExclusionRule =
SbtExclusionRule(organization)
implicit def groupArtifactIDToExcludsionRule(gaid: GroupArtifactID): SbtExclusionRule =
SbtExclusionRule(gaid.groupID, gaid.artifactID, "*", Nil, gaid.crossVersion)
}

View File

@ -24,7 +24,7 @@ trait DependencyBuilders {
}
}
final class GroupID private[sbt] (groupID: String) {
final class GroupID private[sbt] (private[sbt] val groupID: String) {
def %(artifactID: String) = groupArtifact(artifactID, CrossVersion.Disabled)
def %%(artifactID: String): GroupArtifactID = groupArtifact(artifactID, CrossVersion.binary)
@ -38,10 +38,12 @@ final class GroupID private[sbt] (groupID: String) {
nonEmpty(artifactID, "Artifact ID")
new GroupArtifactID(groupID, artifactID, cross)
}
private[this] def deprecationMessage = """Use the cross method on the constructed ModuleID. For example: ("a" % "b" % "1").cross(...)"""
}
final class GroupArtifactID private[sbt] (groupID: String, artifactID: String, crossVersion: CrossVersion) {
final class GroupArtifactID private[sbt] (
private[sbt] val groupID: String,
private[sbt] val artifactID: String,
private[sbt] val crossVersion: CrossVersion) {
def %(revision: String): ModuleID =
{
nonEmpty(revision, "Revision")