diff --git a/ivy/DependencyFilter.scala b/ivy/DependencyFilter.scala new file mode 100644 index 000000000..1773525c6 --- /dev/null +++ b/ivy/DependencyFilter.scala @@ -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) +} \ No newline at end of file diff --git a/ivy/IvyRetrieve.scala b/ivy/IvyRetrieve.scala index f706fc66f..328a33078 100644 --- a/ivy/IvyRetrieve.scala +++ b/ivy/IvyRetrieve.scala @@ -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) -} \ No newline at end of file diff --git a/ivy/UpdateReport.scala b/ivy/UpdateReport.scala new file mode 100644 index 000000000..50097eeeb --- /dev/null +++ b/ivy/UpdateReport.scala @@ -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) + } + } +} \ No newline at end of file