From 82f025bdeca4fc3aad24c814d881634960dcd486 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Fri, 8 Jul 2011 21:54:59 -0400 Subject: [PATCH] warn when there is an sbt version conflict. fixes #80 --- ivy/ConflictWarning.scala | 20 ++++++++++++++++++++ ivy/DependencyFilter.scala | 1 + ivy/IvyActions.scala | 12 ++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 ivy/ConflictWarning.scala diff --git a/ivy/ConflictWarning.scala b/ivy/ConflictWarning.scala new file mode 100644 index 000000000..5d642f04f --- /dev/null +++ b/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 ) + } +} diff --git a/ivy/DependencyFilter.scala b/ivy/DependencyFilter.scala index 1773525c6..e31cd4e24 100644 --- a/ivy/DependencyFilter.scala +++ b/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 { diff --git a/ivy/IvyActions.scala b/ivy/IvyActions.scala index eed985a03..ad0f4cdca 100644 --- a/ivy/IvyActions.scala +++ b/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}