Move `cachedUpdate` to new `DependencyResolver`

The `cachedUpdate` implementation does not need to be in `Defaults`
since it's not using any of the tasks/settings defined there, that's
`updateTask`'s job.

This commit moves the utilities required by `updateTask` to the
`sbt.internal.librarymanagement` namespace.
This commit is contained in:
jvican 2017-04-27 16:00:48 +02:00
parent 1c961e8814
commit e7b8cbfe01
No known key found for this signature in database
GPG Key ID: 42DAFA0F112E8050
2 changed files with 118 additions and 102 deletions

View File

@ -2119,7 +2119,7 @@ object Classpaths {
else (evictionWarningOptions in update).value
}
cachedUpdate(
DependencyResolver.cachedUpdate(
s.cacheStoreFactory.sub(updateCacheName.value),
Reference.display(thisProjectRef.value),
ivyModule.value,
@ -2138,107 +2138,6 @@ object Classpaths {
)
}
private type UpdateInputs = IvyConfiguration :+: ModuleSettings :+: UpdateConfiguration :+: HNil
private[sbt] def cachedUpdate(
cacheStoreFactory: CacheStoreFactory,
label: String,
module: IvySbt#Module,
updateConfig: UpdateConfiguration,
transform: UpdateReport => UpdateReport,
skip: Boolean,
force: Boolean,
depsUpdated: Boolean,
uwConfig: UnresolvedWarningConfiguration,
logicalClock: LogicalClock,
depDir: Option[File],
ewo: EvictionWarningOptions,
mavenStyle: Boolean,
compatWarning: CompatibilityWarningOptions,
log: Logger
): UpdateReport = {
/* Resolve the module settings from the inputs. */
def resolve(inputs: UpdateInputs): UpdateReport = {
import ShowLines._
log.info(s"Updating $label...")
val reportOrUnresolved: Either[UnresolvedWarning, UpdateReport] =
IvyActions.updateEither(module, updateConfig, uwConfig, logicalClock, depDir, log)
val report = reportOrUnresolved match {
case Right(report0) => report0
case Left(unresolvedWarning) =>
unresolvedWarning.lines.foreach(log.warn(_))
throw unresolvedWarning.resolveException
}
log.info("Done updating.")
val finalReport = transform(report)
// Warn of any eviction and compatibility warnings
val ew = EvictionWarning(module, ewo, finalReport, log)
ew.lines foreach { log.warn(_) }
ew.infoAllTheThings foreach { log.info(_) }
CompatibilityWarning.run(compatWarning, module, mavenStyle, log)
finalReport
}
/* Check if a update report is still up to date or we must resolve again. */
def upToDate(inChanged: Boolean, out: UpdateReport): Boolean = {
!force &&
!depsUpdated &&
!inChanged &&
out.allFiles.forall(f => fileUptodate(f, out.stamps)) &&
fileUptodate(out.cachedDescriptor, out.stamps)
}
/* Skip resolve if last output exists, otherwise error. */
def skipResolve(cache: CacheStore): UpdateInputs => UpdateReport = {
import LibraryManagementCodec._
Tracked.lastOutput[UpdateInputs, UpdateReport](cache) {
case (_, Some(out)) => out
case _ =>
sys.error("Skipping update requested, but update has not previously run successfully.")
}
}
def doResolve(cache: CacheStore): UpdateInputs => UpdateReport = {
val doCachedResolve = { (inChanged: Boolean, updateInputs: UpdateInputs) =>
import LibraryManagementCodec._
val cachedResolve = Tracked.lastOutput[UpdateInputs, UpdateReport](cache) {
case (_, Some(out)) if upToDate(inChanged, out) => out
case _ => resolve(updateInputs)
}
import scala.util.control.Exception.catching
catching(classOf[NullPointerException], classOf[OutOfMemoryError])
.withApply { t =>
val resolvedAgain = resolve(updateInputs)
val culprit = t.getClass.getSimpleName
log.warn(s"Update task caching failed due to $culprit.")
log.warn("Report the following output to sbt:")
resolvedAgain.toString.lines foreach { log.warn(_) }
log.trace(t)
resolvedAgain
}
.apply(cachedResolve(updateInputs))
}
import sbt.internal.librarymanagement.AltLibraryManagementCodec._
Tracked.inputChanged(cacheStoreFactory.make("inputs"))(doCachedResolve)
}
// Get the handler to use and feed it in the inputs
val ivyConfig = module.owner.configuration
val settings = module.moduleSettings
val outStore = cacheStoreFactory.make("output")
val handler = if (skip && !force) skipResolve(outStore) else doResolve(outStore)
handler(ivyConfig :+: settings :+: updateConfig :+: HNil)
}
private[this] def fileUptodate(file: File, stamps: Map[File, Long]): Boolean =
stamps.get(file).forall(_ == file.lastModified)
private[sbt] def dependencyPositionsTask: Initialize[Task[Map[ModuleID, SourcePosition]]] =
Def.task {
val projRef = thisProjectRef.value

View File

@ -0,0 +1,117 @@
package sbt.internal.librarymanagement
import java.io.File
import sbt.internal.util.Types._
import sbt.internal.util.HNil
import sbt.librarymanagement._
import sbt.util.{ CacheStore, CacheStoreFactory, Logger, Tracked }
import sbt.librarymanagement.syntax._
import sbt.util.CacheImplicits._
object DependencyResolver {
private type UpdateInputs = IvyConfiguration :+: ModuleSettings :+: UpdateConfiguration :+: HNil
private[sbt] def cachedUpdate(
cacheStoreFactory: CacheStoreFactory,
label: String,
module: IvySbt#Module,
updateConfig: UpdateConfiguration,
transform: UpdateReport => UpdateReport,
skip: Boolean,
force: Boolean,
depsUpdated: Boolean,
uwConfig: UnresolvedWarningConfiguration,
logicalClock: LogicalClock,
depDir: Option[File],
ewo: EvictionWarningOptions,
mavenStyle: Boolean,
compatWarning: CompatibilityWarningOptions,
log: Logger
): UpdateReport = {
/* Resolve the module settings from the inputs. */
def resolve(inputs: UpdateInputs): UpdateReport = {
import sbt.util.ShowLines._
log.info(s"Updating $label...")
val reportOrUnresolved: Either[UnresolvedWarning, UpdateReport] =
IvyActions.updateEither(module, updateConfig, uwConfig, logicalClock, depDir, log)
val report = reportOrUnresolved match {
case Right(report0) => report0
case Left(unresolvedWarning) =>
unresolvedWarning.lines.foreach(log.warn(_))
throw unresolvedWarning.resolveException
}
log.info("Done updating.")
val finalReport = transform(report)
// Warn of any eviction and compatibility warnings
val ew = EvictionWarning(module, ewo, finalReport, log)
ew.lines.foreach(log.warn(_))
ew.infoAllTheThings.foreach(log.info(_))
CompatibilityWarning.run(compatWarning, module, mavenStyle, log)
finalReport
}
/* Check if a update report is still up to date or we must resolve again. */
def upToDate(inChanged: Boolean, out: UpdateReport): Boolean = {
!force &&
!depsUpdated &&
!inChanged &&
out.allFiles.forall(f => fileUptodate(f, out.stamps)) &&
fileUptodate(out.cachedDescriptor, out.stamps)
}
/* Skip resolve if last output exists, otherwise error. */
def skipResolve(cache: CacheStore): UpdateInputs => UpdateReport = {
import sbt.librarymanagement.LibraryManagementCodec._
Tracked.lastOutput[UpdateInputs, UpdateReport](cache) {
case (_, Some(out)) => out
case _ =>
sys.error("Skipping update requested, but update has not previously run successfully.")
}
}
def doResolve(cache: CacheStore): UpdateInputs => UpdateReport = {
val doCachedResolve = { (inChanged: Boolean, updateInputs: UpdateInputs) =>
import sbt.librarymanagement.LibraryManagementCodec._
val cachedResolve = Tracked.lastOutput[UpdateInputs, UpdateReport](cache) {
case (_, Some(out)) if upToDate(inChanged, out) => out
case _ => resolve(updateInputs)
}
import scala.util.control.Exception.catching
catching(classOf[NullPointerException], classOf[OutOfMemoryError])
.withApply { t =>
val resolvedAgain = resolve(updateInputs)
val culprit = t.getClass.getSimpleName
log.warn(s"Update task caching failed due to $culprit.")
log.warn("Report the following output to sbt:")
resolvedAgain.toString.lines foreach {
log.warn(_)
}
log.trace(t)
resolvedAgain
}
.apply(cachedResolve(updateInputs))
}
import sbt.internal.librarymanagement.AltLibraryManagementCodec._
Tracked.inputChanged(cacheStoreFactory.make("inputs"))(doCachedResolve)
}
// Get the handler to use and feed it in the inputs
val ivyConfig = module.owner.configuration
val settings = module.moduleSettings
val outStore = cacheStoreFactory.make("output")
val handler = if (skip && !force) skipResolve(outStore) else doResolve(outStore)
handler(ivyConfig :+: settings :+: updateConfig :+: HNil)
}
private[this] def fileUptodate(file: File, stamps: Map[File, Long]): Boolean =
stamps.get(file).forall(_ == file.lastModified)
}