mirror of https://github.com/sbt/sbt.git
add context-bound-relaxed helpers for write-only Tracked
This commit is contained in:
parent
8429187ecb
commit
6be10901de
|
|
@ -419,6 +419,10 @@ lazy val utilTracking = (project in file("util-tracking"))
|
||||||
name := "Util Tracking",
|
name := "Util Tracking",
|
||||||
libraryDependencies ++= Seq(scalatest % "test"),
|
libraryDependencies ++= Seq(scalatest % "test"),
|
||||||
utilMimaSettings,
|
utilMimaSettings,
|
||||||
|
mimaBinaryIssueFilters ++= Seq(
|
||||||
|
// Private final class constructors changed
|
||||||
|
ProblemFilters.exclude[IncompatibleMethTypeProblem]("sbt.util.Tracked#CacheHelp.this"),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.configure(addSbtIO)
|
.configure(addSbtIO)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import sbt.io.IO
|
||||||
import sbt.io.syntax._
|
import sbt.io.syntax._
|
||||||
import sbt.internal.util.EmptyCacheError
|
import sbt.internal.util.EmptyCacheError
|
||||||
|
|
||||||
import sjsonnew.JsonFormat
|
import sjsonnew.{ JsonFormat, JsonWriter }
|
||||||
import sjsonnew.support.murmurhash.Hasher
|
import sjsonnew.support.murmurhash.Hasher
|
||||||
|
|
||||||
object Tracked {
|
object Tracked {
|
||||||
|
|
@ -95,6 +95,28 @@ object Tracked {
|
||||||
*/
|
*/
|
||||||
def outputChanged[A1: JsonFormat, A2](store: CacheStore)(
|
def outputChanged[A1: JsonFormat, A2](store: CacheStore)(
|
||||||
f: (Boolean, A1) => A2
|
f: (Boolean, A1) => A2
|
||||||
|
): (() => A1) => A2 = {
|
||||||
|
outputChangedW(store)(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a tracker that indicates whether the output returned from `p` has changed or not.
|
||||||
|
*
|
||||||
|
* {{{
|
||||||
|
* val cachedTask = inputChanged(cache / "inputs") { (inChanged, in: Inputs) =>
|
||||||
|
* Tracked.outputChanged(cache / "output") { (outChanged, outputs: FilesInfo[PlainFileInfo]) =>
|
||||||
|
* if (inChanged || outChanged) {
|
||||||
|
* doSomething(label, sources, classpath, outputDirectory, options, log)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* cachedDoc(inputs)(() => exists(outputDirectory.allPaths.get.toSet))
|
||||||
|
* }}}
|
||||||
|
*
|
||||||
|
* This is a variant of `outputChanged` that takes `A1: JsonWriter` as opposed to `A1: JsonFormat`.
|
||||||
|
*/
|
||||||
|
def outputChangedW[A1: JsonWriter, A2](store: CacheStore)(
|
||||||
|
f: (Boolean, A1) => A2
|
||||||
): (() => A1) => A2 = p => {
|
): (() => A1) => A2 = p => {
|
||||||
val cache: SingletonCache[Long] = {
|
val cache: SingletonCache[Long] = {
|
||||||
import CacheImplicits.LongJsonFormat
|
import CacheImplicits.LongJsonFormat
|
||||||
|
|
@ -127,6 +149,27 @@ object Tracked {
|
||||||
def outputChanged[A1: JsonFormat, A2](cacheFile: File)(f: (Boolean, A1) => A2): (() => A1) => A2 =
|
def outputChanged[A1: JsonFormat, A2](cacheFile: File)(f: (Boolean, A1) => A2): (() => A1) => A2 =
|
||||||
outputChanged[A1, A2](CacheStore(cacheFile))(f)
|
outputChanged[A1, A2](CacheStore(cacheFile))(f)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a tracker that indicates whether the output returned from `p` has changed or not.
|
||||||
|
*
|
||||||
|
* {{{
|
||||||
|
* val cachedTask = inputChanged(cache / "inputs") { (inChanged, in: Inputs) =>
|
||||||
|
* Tracked.outputChanged(cache / "output") { (outChanged, outputs: FilesInfo[PlainFileInfo]) =>
|
||||||
|
* if (inChanged || outChanged) {
|
||||||
|
* doSomething(label, sources, classpath, outputDirectory, options, log)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* cachedDoc(inputs)(() => exists(outputDirectory.allPaths.get.toSet))
|
||||||
|
* }}}
|
||||||
|
*
|
||||||
|
* This is a variant of `outputChanged` that takes `A1: JsonWriter` as opposed to `A1: JsonFormat`.
|
||||||
|
*/
|
||||||
|
def outputChangedW[A1: JsonWriter, A2](
|
||||||
|
cacheFile: File
|
||||||
|
)(f: (Boolean, A1) => A2): (() => A1) => A2 =
|
||||||
|
outputChangedW[A1, A2](CacheStore(cacheFile))(f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a tracker that indicates whether the arguments given to f have changed since the most
|
* Creates a tracker that indicates whether the arguments given to f have changed since the most
|
||||||
* recent invocation.
|
* recent invocation.
|
||||||
|
|
@ -144,6 +187,28 @@ object Tracked {
|
||||||
*/
|
*/
|
||||||
def inputChanged[I: JsonFormat: SingletonCache, O](store: CacheStore)(
|
def inputChanged[I: JsonFormat: SingletonCache, O](store: CacheStore)(
|
||||||
f: (Boolean, I) => O
|
f: (Boolean, I) => O
|
||||||
|
): I => O =
|
||||||
|
inputChangedW(store)(f)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a tracker that indicates whether the arguments given to f have changed since the most
|
||||||
|
* recent invocation.
|
||||||
|
*
|
||||||
|
* {{{
|
||||||
|
* val cachedTask = inputChanged(cache / "inputs") { (inChanged, in: Inputs) =>
|
||||||
|
* Tracked.outputChanged(cache / "output") { (outChanged, outputs: FilesInfo[PlainFileInfo]) =>
|
||||||
|
* if (inChanged || outChanged) {
|
||||||
|
* doSomething(label, sources, classpath, outputDirectory, options, log)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* cachedDoc(inputs)(() => exists(outputDirectory.allPaths.get.toSet))
|
||||||
|
* }}}
|
||||||
|
*
|
||||||
|
* This is a variant of `inputChanged` that takes `I: JsonWriter` as opposed to `I: JsonFormat`.
|
||||||
|
*/
|
||||||
|
def inputChangedW[I: JsonWriter, O](store: CacheStore)(
|
||||||
|
f: (Boolean, I) => O
|
||||||
): I => O = { in =>
|
): I => O = { in =>
|
||||||
val cache: SingletonCache[Long] = {
|
val cache: SingletonCache[Long] = {
|
||||||
import CacheImplicits.LongJsonFormat
|
import CacheImplicits.LongJsonFormat
|
||||||
|
|
@ -177,7 +242,29 @@ object Tracked {
|
||||||
): I => O =
|
): I => O =
|
||||||
inputChanged(CacheStore(cacheFile))(f)
|
inputChanged(CacheStore(cacheFile))(f)
|
||||||
|
|
||||||
private final class CacheHelp[I: JsonFormat](val sc: SingletonCache[Long]) {
|
/**
|
||||||
|
* Creates a tracker that indicates whether the arguments given to f have changed since the most
|
||||||
|
* recent invocation.
|
||||||
|
*
|
||||||
|
* {{{
|
||||||
|
* val cachedTask = inputChanged(cache / "inputs") { (inChanged, in: Inputs) =>
|
||||||
|
* Tracked.outputChanged(cache / "output") { (outChanged, outputs: FilesInfo[PlainFileInfo]) =>
|
||||||
|
* if (inChanged || outChanged) {
|
||||||
|
* doSomething(label, sources, classpath, outputDirectory, options, log)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* cachedDoc(inputs)(() => exists(outputDirectory.allPaths.get.toSet))
|
||||||
|
* }}}
|
||||||
|
*
|
||||||
|
* This is a variant of `inputChanged` that takes `I: JsonWriter` as opposed to `I: JsonFormat`.
|
||||||
|
*/
|
||||||
|
def inputChangedW[I: JsonWriter, O](cacheFile: File)(
|
||||||
|
f: (Boolean, I) => O
|
||||||
|
): I => O =
|
||||||
|
inputChangedW(CacheStore(cacheFile))(f)
|
||||||
|
|
||||||
|
private final class CacheHelp[I: JsonWriter](val sc: SingletonCache[Long]) {
|
||||||
import CacheImplicits.implicitHashWriter
|
import CacheImplicits.implicitHashWriter
|
||||||
import CacheImplicits.LongJsonFormat
|
import CacheImplicits.LongJsonFormat
|
||||||
def save(store: CacheStore, value: I): Unit = {
|
def save(store: CacheStore, value: I): Unit = {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import org.scalatest.FlatSpec
|
||||||
import sbt.io.IO
|
import sbt.io.IO
|
||||||
import sbt.io.syntax._
|
import sbt.io.syntax._
|
||||||
import sbt.util.CacheImplicits._
|
import sbt.util.CacheImplicits._
|
||||||
|
import sjsonnew.{ Builder, JsonWriter }
|
||||||
|
|
||||||
import scala.concurrent.Promise
|
import scala.concurrent.Promise
|
||||||
|
|
||||||
|
|
@ -56,6 +57,27 @@ class TrackedSpec extends FlatSpec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"inputChangedW" should "not require the input to have a JsonReader instance" in {
|
||||||
|
case class Input(v: Int)
|
||||||
|
|
||||||
|
implicit val writer = new JsonWriter[Input] {
|
||||||
|
override def write[J](obj: Input, builder: Builder[J]): Unit = builder.writeInt(obj.v)
|
||||||
|
}
|
||||||
|
|
||||||
|
withStore { store =>
|
||||||
|
val input0 = Input(1)
|
||||||
|
|
||||||
|
val cachedFun = Tracked.inputChangedW[Input, Int](store) {
|
||||||
|
case (_, in) => in.v
|
||||||
|
}
|
||||||
|
|
||||||
|
val res0 = cachedFun(input0)
|
||||||
|
assert(res0 === input0.v)
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
"inputChanged" should "detect that the input has not changed" in {
|
"inputChanged" should "detect that the input has not changed" in {
|
||||||
withStore { store =>
|
withStore { store =>
|
||||||
val input0 = "foo"
|
val input0 = "foo"
|
||||||
|
|
@ -113,6 +135,27 @@ class TrackedSpec extends FlatSpec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"outputChangedW" should "not require the input to have a JsonReader instance" in {
|
||||||
|
case class Input(v: Int)
|
||||||
|
|
||||||
|
implicit val writer = new JsonWriter[Input] {
|
||||||
|
override def write[J](obj: Input, builder: Builder[J]): Unit = builder.writeInt(obj.v)
|
||||||
|
}
|
||||||
|
|
||||||
|
withStore { store =>
|
||||||
|
val input0 = Input(1)
|
||||||
|
|
||||||
|
val cachedFun = Tracked.outputChangedW[Input, Int](store) {
|
||||||
|
case (_, in) => in.v
|
||||||
|
}
|
||||||
|
|
||||||
|
val res0 = cachedFun(() => input0)
|
||||||
|
assert(res0 === input0.v)
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
"outputChanged" should "detect that the output has not changed" in {
|
"outputChanged" should "detect that the output has not changed" in {
|
||||||
withStore { store =>
|
withStore { store =>
|
||||||
val beforeCompletion: String = "before-completion"
|
val beforeCompletion: String = "before-completion"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue