Skip to content
Browse files

warn when there is an sbt version conflict. fixes #80

  • Loading branch information...
1 parent 15427d3 commit 1d792c3601ee1564b5e9f1c993840f51c1e2d181 @harrah committed Jul 8, 2011
Showing with 36 additions and 0 deletions.
  1. +20 −0 ivy/ConflictWarning.scala
  2. +1 −0 ivy/DependencyFilter.scala
  3. +12 −0 ivy/IvyActions.scala
  4. +2 −0 main/Defaults.scala
  5. +1 −0 main/Keys.scala
View
20 ivy/ConflictWarning.scala
@@ -0,0 +1,20 @@
+package sbt
+
+ import DependencyFilter._
+
+final case class ConflictWarning(filter: ModuleFilter, group: ModuleID => String, level: Level.Value, failOnConflict: Boolean)
+object ConflictWarning
+{
+ def default: ConflictWarning = ConflictWarning( moduleFilter(organization = GlobFilter("org.scala-tools.sbt") | GlobFilter("org.scala-lang")), (_: ModuleID).organization, Level.Warn, false)
+
+ def apply(config: ConflictWarning, report: UpdateReport, log: Logger)
+ {
+ val conflicts = IvyActions.groupedConflicts(config.filter, config.group)(report)
+ if(!conflicts.isEmpty)
+ log.log(config.level, "Potentially incompatible versions specified:")
+ for( (label, versions) <- conflicts )
+ log.log(config.level, " " + label + ": " + versions.mkString(", "))
+ if(config.failOnConflict && !conflicts.isEmpty)
+ error("Conflicts in " + conflicts.map(_._1).mkString )
+ }
+}
View
1 ivy/DependencyFilter.scala
@@ -32,6 +32,7 @@ object DependencyFilter extends DependencyFilterExtra
implicit def fnToModuleFilter(f: ModuleID => Boolean): ModuleFilter = new ModuleFilter { def apply(m: ModuleID) = f(m) }
implicit def fnToArtifactFilter(f: Artifact => Boolean): ArtifactFilter = new ArtifactFilter { def apply(m: Artifact) = f(m) }
implicit def fnToConfigurationFilter(f: String => Boolean): ConfigurationFilter = new ConfigurationFilter { def apply(c: String) = f(c) }
+ implicit def subDepFilterToFn[Arg](f: SubDepFilter[Arg, _]): Arg => Boolean = f apply _
}
trait DependencyFilter
{
View
12 ivy/IvyActions.scala
@@ -131,6 +131,18 @@ object IvyActions
}
}
+ def groupedConflicts[T](moduleFilter: ModuleFilter, grouping: ModuleID => T)(report: UpdateReport): Map[T, Set[String]] =
+ report.configurations.flatMap { confReport =>
+ val evicted = confReport.evicted.filter(moduleFilter)
+ val evictedSet = evicted.map( m => (m.organization, m.name) ).toSet
+ val conflicted = confReport.allModules.filter( mod => evictedSet( (mod.organization, mod.name) ) )
+ grouped(grouping)(conflicted ++ evicted)
+ } toMap;
+
+ def grouped[T](grouping: ModuleID => T)(mods: Seq[ModuleID]): Map[T, Set[String]] =
+ mods groupBy(grouping) mapValues(_.map(_.revision).toSet)
+
+
def transitiveScratch(ivySbt: IvySbt, label: String, config: GetClassifiersConfiguration, log: Logger): UpdateReport =
{
import config.{configuration => c, id, ivyScala, modules => deps}
View
2 main/Defaults.scala
@@ -576,6 +576,7 @@ object Classpaths
publishLocal <<= publishTask(publishLocalConfiguration, deliverLocal)
)
val baseSettings: Seq[Setting[_]] = Seq(
+ conflictWarning in GlobalScope := ConflictWarning.default,
unmanagedBase <<= baseDirectory / "lib",
normalizedName <<= name(StringUtilities.normalize),
organization <<= organization or normalizedName.identity,
@@ -644,6 +645,7 @@ object Classpaths
update <<= (ivyModule, thisProjectRef, updateConfiguration, cacheDirectory, scalaInstance, streams) map { (module, ref, config, cacheDirectory, si, s) =>
cachedUpdate(cacheDirectory / "update", Project.display(ref), module, config, Some(si), s.log)
},
+ update <<= (conflictWarning, update, streams) map { (config, report, s) => ConflictWarning(config, report, s.log); report },
transitiveClassifiers in GlobalScope :== Seq(SourceClassifier, DocClassifier),
updateClassifiers <<= (ivySbt, projectID, update, transitiveClassifiers in updateClassifiers, updateConfiguration, ivyScala, target in LocalRootProject, appConfiguration, streams) map { (is, pid, up, classifiers, c, ivyScala, out, app, s) =>
withExcludes(out, classifiers, lock(app)) { excludes =>
View
1 main/Keys.scala
@@ -255,6 +255,7 @@ object Keys
val packagedArtifact = TaskKey[(Artifact, File)]("packaged-artifact", "Generates a packaged artifact, returning the Artifact and the produced File.")
val checksums = SettingKey[Seq[String]]("checksums", "The list of checksums to generate and to verify for dependencies.")
+ val conflictWarning = SettingKey[ConflictWarning]("conflict-warning", "Configures warnings for conflicts in dependency management.")
val autoScalaLibrary = SettingKey[Boolean]("auto-scala-library", "Adds a dependency on scala-library if true.")
val sbtResolver = SettingKey[Resolver]("sbt-resolver", "Provides a resolver for obtaining sbt as a dependency.")
val sbtDependency = SettingKey[ModuleID]("sbt-dependency", "Provides a definition for declaring the current version of sbt.")

0 comments on commit 1d792c3

Please sign in to comment.
Something went wrong with that request. Please try again.