mirror of https://github.com/sbt/sbt.git
dependency filters, selecting/filtering UpdateReport
This commit is contained in:
parent
2f2e24c87d
commit
673f9923ab
|
|
@ -0,0 +1,66 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2011 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
trait DependencyFilterExtra
|
||||
{
|
||||
def moduleFilter(organization: NameFilter = AllPassFilter, name: NameFilter = AllPassFilter, revision: NameFilter = AllPassFilter): ModuleFilter =
|
||||
new ModuleFilter {
|
||||
def apply(m: ModuleID): Boolean = organization.accept(m.organization) && name.accept(m.name) && revision.accept(m.revision)
|
||||
}
|
||||
def artifactFilter(name: NameFilter = AllPassFilter, `type`: NameFilter = AllPassFilter, extension: NameFilter = AllPassFilter, classifier: NameFilter = AllPassFilter): ArtifactFilter =
|
||||
new ArtifactFilter {
|
||||
def apply(a: Artifact): Boolean = name.accept(a.name) && `type`.accept(a.`type`) && extension.accept(a.extension) && classifier.accept(a.classifier getOrElse "")
|
||||
}
|
||||
def configurationFilter(name: NameFilter = AllPassFilter): ConfigurationFilter =
|
||||
new ConfigurationFilter {
|
||||
def apply(c: String): Boolean = name.accept(c)
|
||||
}
|
||||
}
|
||||
object DependencyFilter extends DependencyFilterExtra
|
||||
{
|
||||
def make(configuration: ConfigurationFilter = configurationFilter(), module: ModuleFilter = moduleFilter(), artifact: ArtifactFilter = artifactFilter()): DependencyFilter =
|
||||
new DependencyFilter {
|
||||
def apply(c: String, m: ModuleID, a: Artifact): Boolean = configuration(c) && module(m) && artifact(a)
|
||||
}
|
||||
def apply(x: DependencyFilter, y: DependencyFilter, combine: (Boolean, Boolean) => Boolean): DependencyFilter =
|
||||
new DependencyFilter {
|
||||
def apply(c: String, m: ModuleID, a: Artifact): Boolean = combine(x(c, m, a), y(c, m, a))
|
||||
}
|
||||
def allPass: DependencyFilter = configurationFilter()
|
||||
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) }
|
||||
}
|
||||
trait DependencyFilter
|
||||
{
|
||||
def apply(configuration: String, module: ModuleID, artifact: Artifact): Boolean
|
||||
final def &&(o: DependencyFilter) = DependencyFilter(this, o, _ && _)
|
||||
final def ||(o: DependencyFilter) = DependencyFilter(this, o, _ || _)
|
||||
final def -- (o: DependencyFilter) = DependencyFilter(this, o, _ && !_)
|
||||
}
|
||||
sealed trait SubDepFilter[Arg, Self <: SubDepFilter[Arg, Self]] extends DependencyFilter
|
||||
{ self: Self =>
|
||||
def apply(a: Arg): Boolean
|
||||
protected def make(f: Arg => Boolean): Self
|
||||
final def &(o: Self): Self = combine(o, _ && _)
|
||||
final def |(o: Self): Self = combine(o, _ || _)
|
||||
final def -(o: Self): Self = combine(o, _ && !_)
|
||||
private[this] def combine(o: Self, f: (Boolean, Boolean) => Boolean): Self = make( (m: Arg) => f(this(m), o(m)) )
|
||||
}
|
||||
trait ModuleFilter extends SubDepFilter[ModuleID, ModuleFilter]
|
||||
{
|
||||
protected final def make(f: ModuleID => Boolean) = new ModuleFilter { def apply(m: ModuleID) = f(m) }
|
||||
final def apply(configuration: String, module: ModuleID, artifact: Artifact): Boolean = apply(module)
|
||||
}
|
||||
trait ArtifactFilter extends SubDepFilter[Artifact, ArtifactFilter]
|
||||
{
|
||||
protected final def make(f: Artifact => Boolean) = new ArtifactFilter { def apply(m: Artifact) = f(m) }
|
||||
final def apply(configuration: String, module: ModuleID, artifact: Artifact): Boolean = apply(artifact)
|
||||
}
|
||||
trait ConfigurationFilter extends SubDepFilter[String, ConfigurationFilter]
|
||||
{
|
||||
protected final def make(f: String => Boolean) = new ConfigurationFilter { def apply(m: String) = f(m) }
|
||||
final def apply(configuration: String, module: ModuleID, artifact: Artifact): Boolean = apply(configuration)
|
||||
}
|
||||
|
|
@ -50,30 +50,3 @@ object IvyRetrieve
|
|||
def configurationReport(confReport: ConfigurationResolveReport): ConfigurationReport =
|
||||
new ConfigurationReport(confReport.getConfiguration, moduleReports(confReport))
|
||||
}
|
||||
|
||||
final class UpdateReport(val configurations: Seq[ConfigurationReport])
|
||||
{
|
||||
override def toString = "Update report:\n" + configurations.mkString
|
||||
def allModules: Seq[ModuleID] = configurations.flatMap(_.allModules).distinct
|
||||
def retrieve(f: (String, ModuleID, Artifact, File) => File): UpdateReport =
|
||||
new UpdateReport(configurations map { _ retrieve f} )
|
||||
def configuration(s: String) = configurations.find(_.configuration == s)
|
||||
}
|
||||
final class ConfigurationReport(val configuration: String, val modules: Seq[ModuleReport])
|
||||
{
|
||||
override def toString = "\t" + configuration + ":\n" + modules.mkString
|
||||
def allModules: Seq[ModuleID] = modules.map(_.module)
|
||||
def retrieve(f: (String, ModuleID, Artifact, File) => File): ConfigurationReport =
|
||||
new ConfigurationReport(configuration, modules map { _.retrieve( (mid,art,file) => f(configuration, mid, art, file)) })
|
||||
}
|
||||
final class ModuleReport(val module: ModuleID, val artifacts: Seq[(Artifact, File)], val missingArtifacts: Seq[Artifact])
|
||||
{
|
||||
override def toString =
|
||||
{
|
||||
val arts = artifacts.map(_.toString) ++ missingArtifacts.map(art => "(MISSING) " + art)
|
||||
"\t\t" + module + ": " +
|
||||
(if(arts.size <= 1) "" else "\n\t\t\t") + arts.mkString("\n\t\t\t") + "\n"
|
||||
}
|
||||
def retrieve(f: (ModuleID, Artifact, File) => File): ModuleReport =
|
||||
new ModuleReport(module, artifacts.map { case (art,file) => (art, f(module, art, file)) }, missingArtifacts)
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2011 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import java.io.File
|
||||
|
||||
final class UpdateReport(val configurations: Seq[ConfigurationReport])
|
||||
{
|
||||
override def toString = "Update report:\n" + configurations.mkString
|
||||
def allModules: Seq[ModuleID] = configurations.flatMap(_.allModules).distinct
|
||||
def retrieve(f: (String, ModuleID, Artifact, File) => File): UpdateReport =
|
||||
new UpdateReport(configurations map { _ retrieve f} )
|
||||
def configuration(s: String) = configurations.find(_.configuration == s)
|
||||
}
|
||||
final class ConfigurationReport(val configuration: String, val modules: Seq[ModuleReport])
|
||||
{
|
||||
override def toString = "\t" + configuration + ":\n" + modules.mkString
|
||||
def allModules: Seq[ModuleID] = modules.map(_.module)
|
||||
def retrieve(f: (String, ModuleID, Artifact, File) => File): ConfigurationReport =
|
||||
new ConfigurationReport(configuration, modules map { _.retrieve( (mid,art,file) => f(configuration, mid, art, file)) })
|
||||
}
|
||||
final class ModuleReport(val module: ModuleID, val artifacts: Seq[(Artifact, File)], val missingArtifacts: Seq[Artifact])
|
||||
{
|
||||
override def toString =
|
||||
{
|
||||
val arts = artifacts.map(_.toString) ++ missingArtifacts.map(art => "(MISSING) " + art)
|
||||
"\t\t" + module + ": " +
|
||||
(if(arts.size <= 1) "" else "\n\t\t\t") + arts.mkString("\n\t\t\t") + "\n"
|
||||
}
|
||||
def retrieve(f: (ModuleID, Artifact, File) => File): ModuleReport =
|
||||
new ModuleReport(module, artifacts.map { case (art,file) => (art, f(module, art, file)) }, missingArtifacts)
|
||||
}
|
||||
object UpdateReport
|
||||
{
|
||||
implicit def richUpdateReport(report: UpdateReport): RichUpdateReport = new RichUpdateReport(report)
|
||||
final class RichUpdateReport(report: UpdateReport)
|
||||
{
|
||||
import DependencyFilter._
|
||||
|
||||
def allFiles: Seq[File] = matching(DependencyFilter.allPass)
|
||||
def matching(f: DependencyFilter): Seq[File] = select0(f).distinct
|
||||
def select(configuration: ConfigurationFilter = configurationFilter(), module: ModuleFilter = moduleFilter(), artifact: ArtifactFilter = artifactFilter()): Seq[File] =
|
||||
matching(DependencyFilter.make(configuration, module, artifact))
|
||||
|
||||
private[this] def select0(f: DependencyFilter): Seq[File] =
|
||||
for(cReport <- report.configurations; mReport <- cReport.modules; (artifact, file) <- mReport.artifacts if f(cReport.configuration, mReport.module, artifact)) yield {
|
||||
if(file == null) error("Null file: conf=" + cReport.configuration + ", module=" + mReport.module + ", art: " + artifact)
|
||||
file
|
||||
}
|
||||
|
||||
def filter(f: DependencyFilter): UpdateReport =
|
||||
{
|
||||
val newConfigurations = report.configurations.map { confReport =>
|
||||
import confReport._
|
||||
val newModules =
|
||||
modules map { modReport =>
|
||||
import modReport._
|
||||
val newArtifacts = artifacts filter { case (art, file) => f(configuration, module, art) }
|
||||
val newMissing = missingArtifacts filter { art => f(configuration, module, art) }
|
||||
new ModuleReport(module, newArtifacts, newMissing)
|
||||
}
|
||||
new ConfigurationReport(configuration, newModules)
|
||||
}
|
||||
new UpdateReport(newConfigurations)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -482,7 +482,7 @@ object Classpaths
|
|||
moduleID :== normalizedName,
|
||||
defaultConfiguration in GlobalScope :== Some(Configurations.Compile),
|
||||
defaultConfigurationMapping in GlobalScope <<= defaultConfiguration{ case Some(d) => "*->" + d.name; case None => "*->*" },
|
||||
ivyPaths <<= (baseDirectory, appConfiguration) { (base, app) => new IvyPaths(base, Option(app.provider.scalaProvider.launcher.ivyHome)) },
|
||||
ivyPaths <<= (baseDirectory, appConfiguration) { (base, app) => new IvyPaths(base, Option(app.provider.scalaProvider.launcher.ivyHome).map(_ / "cache")) },
|
||||
otherResolvers <<= publishTo(_.toList),
|
||||
projectResolver <<= projectResolverTask,
|
||||
projectDependencies <<= projectDependenciesTask,
|
||||
|
|
@ -565,7 +565,7 @@ object Classpaths
|
|||
val f =
|
||||
Tracked.inputChanged(cacheFile / "inputs") { (inChanged: Boolean, in: In) =>
|
||||
val outCache = Tracked.lastOutput[In, UpdateReport](cacheFile / "output") {
|
||||
case (_, Some(out)) if !inChanged && allFiles(out).forall(_.exists) => out
|
||||
case (_, Some(out)) if !inChanged && out.allFiles.forall(_.exists) => out
|
||||
case _ => work(in)
|
||||
}
|
||||
outCache(in)
|
||||
|
|
@ -726,16 +726,8 @@ object Classpaths
|
|||
flatten(defaultConfiguration in p get data) getOrElse Configurations.Default
|
||||
def flatten[T](o: Option[Option[T]]): Option[T] = o flatMap identity
|
||||
|
||||
def managedJars(config: Configuration, jarTypes: Set[String], up: UpdateReport): Classpath = managedFiles(config, up)(isJar(jarTypes))
|
||||
def allFiles(up: UpdateReport): Seq[File] = data( up.configurations flatMap { cr => allJars(cr)(_ => true) }).distinct
|
||||
def managedFiles(config: Configuration, up: UpdateReport)(pred: Artifact => Boolean): Classpath =
|
||||
allJars( confReport(config.name, up) )(pred)
|
||||
def confReport(config: String, up: UpdateReport): ConfigurationReport =
|
||||
up.configuration(config) getOrElse error("Configuration '" + config + "' unresolved by 'update'.")
|
||||
def allJars(cr: ConfigurationReport)(pred: Artifact => Boolean): Seq[File] = cr.modules.flatMap(mr => allJars(mr.artifacts)(pred))
|
||||
def allJars(as: Seq[(Artifact,File)])(pred: Artifact => Boolean): Seq[File] = as collect { case (a, f) if pred(a) => f }
|
||||
def isJar(jarTypes: Set[String])(a: Artifact): Boolean =
|
||||
jarTypes contains a.`type`
|
||||
|
||||
lazy val dbResolver = Resolver.url("sbt-db", new URL("http://databinder.net/repo/"))(Resolver.ivyStylePatterns)
|
||||
|
||||
import DependencyFilter._
|
||||
def managedJars(config: Configuration, jarTypes: Set[String], up: UpdateReport): Classpath = up.select( configuration = configurationFilter(config.name), artifact = artifactFilter(`type` = jarTypes) )
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010, 2011 Mark Harrah
|
||||
*/
|
||||
package object sbt extends sbt.std.TaskExtra with sbt.Types with sbt.ProcessExtra with sbt.impl.DependencyBuilders with sbt.PathExtra with sbt.ProjectExtra
|
||||
package object sbt extends sbt.std.TaskExtra with sbt.Types with sbt.ProcessExtra with sbt.impl.DependencyBuilders with sbt.PathExtra with sbt.ProjectExtra with sbt.DependencyFilterExtra
|
||||
{
|
||||
type Setting[T] = Project.Setting[T]
|
||||
type ScopedKey[T] = Project.ScopedKey[T]
|
||||
|
|
|
|||
|
|
@ -56,6 +56,12 @@ object NothingFilter extends NameFilter
|
|||
def accept(name: String) = false
|
||||
}
|
||||
|
||||
object NameFilter
|
||||
{
|
||||
implicit def fnToNameFilter(f: String => Boolean): NameFilter = new NameFilter {
|
||||
def accept(name: String) = f(name)
|
||||
}
|
||||
}
|
||||
object GlobFilter
|
||||
{
|
||||
implicit def apply(expression: String): NameFilter =
|
||||
|
|
|
|||
Loading…
Reference in New Issue