invalidate 'update' cache when 'update' cache of a dependency is invalidated, fixes #246

This commit is contained in:
Mark Harrah 2011-10-30 18:38:37 -04:00
parent 2805dbde8f
commit b154468097
6 changed files with 43 additions and 5 deletions

View File

@ -233,6 +233,9 @@ object Defaults extends BuildCommon
def watchTransitiveSourcesTask: Initialize[Task[Seq[File]]] =
inDependencies[Task[Seq[File]]](watchSources.task, const(std.TaskExtra.constant(Nil)), aggregate = true, includeRoot = true) apply { _.join.map(_.flatten) }
def transitiveUpdateTask: Initialize[Task[Seq[UpdateReport]]] =
forDependencies(ref => (update.task in ref).?, aggregate = false, includeRoot = false) apply( _.flatten.join)
def watchSetting: Initialize[Watched] = (pollInterval, thisProjectRef, watchingMessage, triggeredMessage) { (interval, base, msg, trigMsg) =>
new Watched {
val scoped = watchTransitiveSources in base
@ -543,8 +546,11 @@ object Defaults extends BuildCommon
}
def inDependencies[T](key: SettingKey[T], default: ProjectRef => T, includeRoot: Boolean = true, classpath: Boolean = true, aggregate: Boolean = false): Initialize[Seq[T]] =
forDependencies[T,T](ref => (key in ref) ?? default(ref), includeRoot, classpath, aggregate)
def forDependencies[T,V](init: ProjectRef => Initialize[V], includeRoot: Boolean = true, classpath: Boolean = true, aggregate: Boolean = false): Initialize[Seq[V]] =
Project.bind( (loadedBuild, thisProjectRef).identity ) { case (lb, base) =>
transitiveDependencies(base, lb, includeRoot, classpath, aggregate) map ( ref => (key in ref) ?? default(ref) ) join ;
transitiveDependencies(base, lb, includeRoot, classpath, aggregate) map init join ;
}
def transitiveDependencies(base: ProjectRef, structure: LoadedBuild, includeRoot: Boolean, classpath: Boolean = true, aggregate: Boolean = false): Seq[ProjectRef] =
@ -722,8 +728,10 @@ object Classpaths
},
ivySbt <<= ivySbt0,
ivyModule <<= (ivySbt, moduleSettings) map { (ivySbt, settings) => new ivySbt.Module(settings) },
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)
transitiveUpdate <<= transitiveUpdateTask,
update <<= (ivyModule, thisProjectRef, updateConfiguration, cacheDirectory, scalaInstance, transitiveUpdate, streams) map { (module, ref, config, cacheDirectory, si, reports, s) =>
val depsUpdated = reports.exists(!_.stats.cached)
cachedUpdate(cacheDirectory / "update", Project.display(ref), module, config, Some(si), depsUpdated, s.log)
},
update <<= (conflictWarning, update, streams) map { (config, report, s) => ConflictWarning(config, report, s.log); report },
transitiveClassifiers in GlobalScope :== Seq(SourceClassifier, DocClassifier),
@ -798,7 +806,7 @@ object Classpaths
}})
}
def cachedUpdate(cacheFile: File, label: String, module: IvySbt#Module, config: UpdateConfiguration, scalaInstance: Option[ScalaInstance], log: Logger): UpdateReport =
def cachedUpdate(cacheFile: File, label: String, module: IvySbt#Module, config: UpdateConfiguration, scalaInstance: Option[ScalaInstance], depsUpdated: Boolean, log: Logger): UpdateReport =
{
implicit val updateCache = updateIC
implicit val updateReport = updateReportF
@ -809,11 +817,16 @@ object Classpaths
log.info("Done updating.")
scalaInstance match { case Some(si) => substituteScalaFiles(si, r); case None => r }
}
def uptodate(inChanged: Boolean, out: UpdateReport): Boolean =
!depsUpdated &&
!inChanged &&
out.allFiles.forall(_.exists) &&
out.cachedDescriptor.exists
val f =
Tracked.inputChanged(cacheFile / "inputs") { (inChanged: Boolean, in: In) =>
val outCache = Tracked.lastOutput[In, UpdateReport](cacheFile / "output") {
case (_, Some(out)) if !inChanged && out.allFiles.forall(_.exists) && out.cachedDescriptor.exists => out
case (_, Some(out)) if uptodate(inChanged, out) => out
case _ => work(in)
}
outCache(in)

View File

@ -231,6 +231,7 @@ object Keys
val ivySbt = TaskKey[IvySbt]("ivy-sbt", "Provides the sbt interface to Ivy.")
val ivyModule = TaskKey[IvySbt#Module]("ivy-module", "Provides the sbt interface to a configured Ivy module.")
val update = TaskKey[UpdateReport]("update", "Resolves and optionally retrieves dependencies, producing a report.")
val transitiveUpdate = TaskKey[Seq[UpdateReport]]("transitive-update", "UpdateReports for the internal dependencies of this project.")
val updateClassifiers = TaskKey[UpdateReport]("update-classifiers", "Resolves and optionally retrieves classified artifacts, such as javadocs and sources, for dependency definitions, transitively.", update)
val transitiveClassifiers = SettingKey[Seq[String]]("transitive-classifiers", "List of classifiers used for transitively obtaining extra artifacts for sbt or declared dependencies.")
val updateSbtClassifiers = TaskKey[UpdateReport]("update-sbt-classifiers", "Resolves and optionally retrieves classifiers, such as javadocs and sources, for sbt, transitively.", updateClassifiers)

View File

@ -0,0 +1,3 @@
object A {
def apply(x: org.junit.runners.JUnit4) = ()
}

View File

@ -0,0 +1 @@
libraryDependencies += "junit" % "junit" % "4.5"

View File

@ -0,0 +1,9 @@
import sbt._
import Keys._
object P extends Build
{
lazy val root = Project("root", file("."))
lazy val a = Project("a", file("a")) dependsOn(b)
lazy val b = Project("b", file("b"))
}

View File

@ -0,0 +1,11 @@
> a/compile
$ copy-file changes/A.scala a/A.scala
-> a/compile
$ copy-file changes/b.sbt b/build.sbt
> reload
> a/compile
$ delete b/build.sbt
> reload
-> a/compile