Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

cache failing classifiers. fixes #46

  • Loading branch information...
commit c4ac9445e347f8e3638c3cfbbb5f25bba08010d5 1 parent 4c770e8
@harrah authored
View
32 ivy/IvyActions.scala
@@ -27,6 +27,8 @@ final class PublishConfiguration(val ivyFile: Option[File], val resolverName: St
final class UpdateConfiguration(val retrieve: Option[RetrieveConfiguration], val missingOk: Boolean, val logging: UpdateLogging.Value)
final class RetrieveConfiguration(val retrieveDirectory: File, val outputPattern: String)
final case class MakePomConfiguration(file: File, configurations: Option[Iterable[Configuration]] = None, extra: NodeSeq = NodeSeq.Empty, process: XNode => XNode = n => n, filterRepositories: MavenRepository => Boolean = _ => true, allRepositories: Boolean)
+ // exclude is a map on a restricted ModuleID
+final case class GetClassifiersConfiguration(id: ModuleID, modules: Seq[ModuleID], classifiers: Seq[String], exclude: Map[ModuleID, Set[String]], configuration: UpdateConfiguration, ivyScala: Option[IvyScala])
/** Configures logging during an 'update'. `level` determines the amount of other information logged.
* `Full` is the default and logs the most.
@@ -129,24 +131,40 @@ object IvyActions
}
}
- def transitiveScratch(ivySbt: IvySbt, id: ModuleID, label: String, deps: Seq[ModuleID], classifiers: Seq[String], c: UpdateConfiguration, ivyScala: Option[IvyScala], log: Logger): UpdateReport =
+ def transitiveScratch(ivySbt: IvySbt, label: String, config: GetClassifiersConfiguration, log: Logger): UpdateReport =
{
+ import config.{configuration => c, id, ivyScala, modules => deps}
val base = restrictedCopy(id).copy(name = id.name + "$" + label)
val module = new ivySbt.Module(InlineConfiguration(base, deps).copy(ivyScala = ivyScala))
val report = update(module, c, log)
- transitive(ivySbt, id, report, classifiers, c, ivyScala, log)
+ val newConfig = config.copy(modules = report.allModules)
+ updateClassifiers(ivySbt, newConfig, log)
}
- def transitive(ivySbt: IvySbt, module: ModuleID, report: UpdateReport, classifiers: Seq[String], c: UpdateConfiguration, ivyScala: Option[IvyScala], log: Logger): UpdateReport =
- updateClassifiers(ivySbt, module, report.allModules, classifiers, new UpdateConfiguration(c.retrieve, true, c.logging), ivyScala, log)
- def updateClassifiers(ivySbt: IvySbt, id: ModuleID, modules: Seq[ModuleID], classifiers: Seq[String], configuration: UpdateConfiguration, ivyScala: Option[IvyScala], log: Logger): UpdateReport =
+ def updateClassifiers(ivySbt: IvySbt, config: GetClassifiersConfiguration, log: Logger): UpdateReport =
{
+ import config.{configuration => c, _}
assert(!classifiers.isEmpty, "classifiers cannot be empty")
val baseModules = modules map restrictedCopy
- val deps = baseModules.distinct map { m => m.copy(explicitArtifacts = classifiers map { c => Artifact.classified(m.name, c) }) }
+ val deps = baseModules.distinct flatMap classifiedArtifacts(classifiers, exclude)
val base = restrictedCopy(id).copy(name = id.name + classifiers.mkString("$","_",""))
val module = new ivySbt.Module(InlineConfiguration(base, deps).copy(ivyScala = ivyScala))
- update(module, configuration, log)
+ val upConf = new UpdateConfiguration(c.retrieve, true, c.logging)
+ update(module, upConf, log)
}
+ def classifiedArtifacts(classifiers: Seq[String], exclude: Map[ModuleID, Set[String]])(m: ModuleID): Option[ModuleID] =
+ {
+ val excluded = exclude getOrElse(m, Set.empty)
+ val included = classifiers filterNot excluded
+ if(included.isEmpty) None else Some(m.copy(explicitArtifacts = classifiedArtifacts(m.name, included) ))
+ }
+ def addExcluded(report: UpdateReport, classifiers: Seq[String], exclude: Map[ModuleID, Set[String]]): UpdateReport =
+ report.addMissing { id => classifiedArtifacts(id.name, classifiers filter exclude.getOrElse(id, Set.empty[String])) }
+ def classifiedArtifacts(name: String, classifiers: Seq[String]): Seq[Artifact] =
+ classifiers map { c => Artifact.classified(name, c) }
+
+ def extractExcludes(report: UpdateReport): Map[ModuleID, Set[String]] =
+ report.allMissing flatMap { case (_, mod, art) => art.classifier.map { c => (restrictedCopy(mod), c) } } groupBy(_._1) map { case (mod, pairs) => (mod, pairs.map(_._2).toSet) }
+
private[this] def restrictedCopy(m: ModuleID) = ModuleID(m.organization, m.name, m.revision, crossVersion = m.crossVersion)
private[this] def resolve(logging: UpdateLogging.Value)(ivy: Ivy, module: DefaultModuleDescriptor, defaultConf: String): (ResolveReport, Option[ResolveException]) =
{
View
48 ivy/UpdateReport.scala
@@ -88,36 +88,40 @@ object UpdateReport
/** Constructs a new report that only contains files matching the specified filter.*/
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)
+ moduleReportMap { (configuration, 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 UpdateReport(report.cachedDescriptor, newConfigurations)
- }
def substitute(f: (String, ModuleID, Seq[(Artifact, File)]) => Seq[(Artifact, File)]): UpdateReport =
+ moduleReportMap { (configuration, modReport) =>
+ val newArtifacts = f(configuration, modReport.module, modReport.artifacts)
+ new ModuleReport(modReport.module, newArtifacts, Nil)
+ }
+
+ def toSeq: Seq[(String, ModuleID, Artifact, File)] =
+ for(confReport <- report.configurations; modReport <- confReport.modules; (artifact, file) <- modReport.artifacts) yield
+ (confReport.configuration, modReport.module, artifact, file)
+
+ def allMissing: Seq[(String, ModuleID, Artifact)] =
+ for(confReport <- report.configurations; modReport <- confReport.modules; artifact <- modReport.missingArtifacts) yield
+ (confReport.configuration, modReport.module, artifact)
+
+ def addMissing(f: ModuleID => Seq[Artifact]): UpdateReport =
+ moduleReportMap { (configuration, modReport) =>
+ import modReport._
+ new ModuleReport(module, artifacts, (missingArtifacts ++ f(module)).distinct)
+ }
+
+ def moduleReportMap(f: (String, ModuleReport) => ModuleReport): UpdateReport =
{
val newConfigurations = report.configurations.map { confReport =>
import confReport._
- val newModules =
- modules map { modReport =>
- val newArtifacts = f(configuration, modReport.module, modReport.artifacts)
- new ModuleReport(modReport.module, newArtifacts, Nil)
- }
+ val newModules = modules map { modReport => f(configuration, modReport) }
new ConfigurationReport(configuration, newModules)
}
new UpdateReport(report.cachedDescriptor, newConfigurations)
}
-
- def toSeq: Seq[(String, ModuleID, Artifact, File)] =
- for(confReport <- report.configurations; modReport <- confReport.modules; (artifact, file) <- modReport.artifacts) yield
- (confReport.configuration, modReport.module, artifact, file)
}
}
View
29 main/Defaults.scala
@@ -18,6 +18,7 @@ package sbt
import descriptor.ModuleDescriptor, id.ModuleRevisionId
import java.io.File
import java.net.URL
+ import java.util.concurrent.Callable
import sbinary.DefaultProtocol.StringFormat
import Cache.seqFormat
@@ -636,11 +637,16 @@ object Classpaths
cachedUpdate(cacheDirectory / "update", Project.display(ref), module, config, Some(si), s.log)
},
transitiveClassifiers in GlobalScope :== Seq(SourceClassifier, DocClassifier),
- updateClassifiers <<= (ivySbt, projectID, update, transitiveClassifiers, updateConfiguration, ivyScala, streams) map { (is, pid, up, classifiers, c, ivyScala, s) =>
- IvyActions.transitive(is, pid, up, classifiers, c, ivyScala, s.log)
+ updateClassifiers <<= (ivySbt, projectID, update, transitiveClassifiers, updateConfiguration, ivyScala, baseDirectory in ThisBuild, appConfiguration, streams) map { (is, pid, up, classifiers, c, ivyScala, out, app, s) =>
+ withExcludes(out, classifiers, lock(app)) { excludes =>
+ IvyActions.updateClassifiers(is, GetClassifiersConfiguration(pid, up.allModules, classifiers, excludes, c, ivyScala), s.log)
+ }
},
- updateSbtClassifiers <<= (ivySbt, projectID, transitiveClassifiers, updateConfiguration, sbtDependency, ivyScala, streams) map { (is, pid, classifiers, c, sbtDep, ivyScala, s) =>
- IvyActions.transitiveScratch(is, pid, "sbt", sbtDep :: Nil, classifiers, c, ivyScala, s.log)
+ updateSbtClassifiers <<= (ivySbt, projectID, transitiveClassifiers, updateConfiguration, sbtDependency, ivyScala, baseDirectory in ThisBuild, appConfiguration, streams) map {
+ (is, pid, classifiers, c, sbtDep, ivyScala, out, app, s) =>
+ withExcludes(out, classifiers, lock(app)) { excludes =>
+ IvyActions.transitiveScratch(is, "sbt", GetClassifiersConfiguration(pid, sbtDep :: Nil, classifiers, excludes, c, ivyScala), s.log)
+ }
},
sbtResolver in GlobalScope :== typesafeResolver,
sbtDependency in GlobalScope <<= appConfiguration { app =>
@@ -662,7 +668,20 @@ object Classpaths
}
import Cache._
- import CacheIvy.{classpathFormat, /*publishIC,*/ updateIC, updateReportF}
+ import CacheIvy.{classpathFormat, /*publishIC,*/ updateIC, updateReportF, excludeMap}
+
+ def withExcludes(out: File, classifiers: Seq[String], lock: xsbti.GlobalLock)(f: Map[ModuleID, Set[String]] => UpdateReport): UpdateReport =
+ {
+ val exclName = "exclude_classifiers"
+ val file = out / exclName
+ lock(out / (exclName + ".lock"), new Callable[UpdateReport] { def call = {
+ val excludes = CacheIO.fromFile[Map[ModuleID, Set[String]]](excludeMap, Map.empty[ModuleID, Set[String]])(file)
+ val report = f(excludes)
+ val allExcludes = excludes ++ IvyActions.extractExcludes(report)
+ CacheIO.toFile(excludeMap)(allExcludes)(file)
+ IvyActions.addExcluded(report, classifiers, allExcludes)
+ }})
+ }
def cachedUpdate(cacheFile: File, label: String, module: IvySbt#Module, config: UpdateConfiguration, scalaInstance: Option[ScalaInstance], log: Logger): UpdateReport =
{
View
5 main/actions/CacheIvy.scala
@@ -52,11 +52,12 @@ object CacheIvy
implicit def wrapHL[W, H, T <: HList](implicit f: W => H :+: T, cache: InputCache[H :+: T]): InputCache[W] =
Cache.wrapIn(f, cache)
- def updateIC: InputCache[IvyConfiguration :+: ModuleSettings :+: UpdateConfiguration :+: HNil] = implicitly
+ lazy val excludeMap: Format[Map[ModuleID, Set[String]]] = implicitly
+ lazy val updateIC: InputCache[IvyConfiguration :+: ModuleSettings :+: UpdateConfiguration :+: HNil] = implicitly
/* def deliverIC: InputCache[IvyConfiguration :+: ModuleSettings :+: DeliverConfiguration :+: HNil] = implicitly
def publishIC: InputCache[IvyConfiguration :+: ModuleSettings :+: PublishConfiguration :+: HNil] = implicitly*/
- def updateReportF: Format[UpdateReport] =
+ lazy val updateReportF: Format[UpdateReport] =
{
import DefaultProtocol.{BooleanFormat, FileFormat, StringFormat}
updateReportFormat
Please sign in to comment.
Something went wrong with that request. Please try again.