mirror of https://github.com/sbt/sbt.git
Cleaning up tasks and caching
This commit is contained in:
parent
4bd6f9627b
commit
604a5413c9
|
|
@ -23,18 +23,23 @@ object Cache extends BasicCacheImplicits with SBinaryFormats with HListCacheImpl
|
|||
def wrapOutputCache[O,DO](implicit convert: O => DO, reverse: DO => O, base: OutputCache[DO]): OutputCache[O] =
|
||||
new WrappedOutputCache[O,DO](convert, reverse, base)
|
||||
|
||||
/* Note: Task[O] { type Input = I } is written out because ITask[I,O] did not work (type could not be inferred properly) with a task
|
||||
* with an HList input.*/
|
||||
def apply[I,O](task: Task[O] { type Input = I }, file: File)(implicit cache: Cache[I,O]): Task[O] { type Input = I } =
|
||||
task match { case m: M[I,O,_] =>
|
||||
new M[I,O,Result[O]](None)(m.dependencies)(m.extract)(computeWithCache(m, cache, file))
|
||||
}
|
||||
private def computeWithCache[I,O](m: M[I,O,_], cache: Cache[I,O], file: File)(in: I): Result[O] =
|
||||
cache(file)(in) match
|
||||
{
|
||||
case Left(value) => Value(value)
|
||||
case Right(store) => m.map { out => store(out); out }
|
||||
}
|
||||
def apply[I,O](file: File)(f: I => Task[O])(implicit cache: Cache[I,O]): I => Task[O] =
|
||||
in =>
|
||||
cache(file)(in) match
|
||||
{
|
||||
case Left(value) => Task(value)
|
||||
case Right(store) => f(in) map { out => store(out); out }
|
||||
}
|
||||
def cached[I,O](file: File)(f: I => O)(implicit cache: Cache[I,O]): I => O =
|
||||
in =>
|
||||
cache(file)(in) match
|
||||
{
|
||||
case Left(value) => value
|
||||
case Right(store) =>
|
||||
val out = f(in)
|
||||
store(out)
|
||||
out
|
||||
}
|
||||
}
|
||||
trait BasicCacheImplicits extends NotNull
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
package xsbt
|
||||
|
||||
import java.io.{InputStream,OutputStream}
|
||||
import metascala.HLists.{HCons,HList,HNil}
|
||||
|
||||
import HLists._
|
||||
class HNilInputCache extends NoInputCache[HNil]
|
||||
class HConsInputCache[H,T <: HList](val headCache: InputCache[H], val tailCache: InputCache[T]) extends InputCache[HCons[H,T]]
|
||||
{
|
||||
def uptodate(in: HCons[H,T])(cacheStream: InputStream) =
|
||||
{
|
||||
lazy val headResult = headCache.uptodate(in.head)(cacheStream)
|
||||
lazy val tailResult = tailCache.uptodate(in.tail)(cacheStream)
|
||||
val headResult = headCache.uptodate(in.head)(cacheStream)
|
||||
val tailResult = tailCache.uptodate(in.tail)(cacheStream)
|
||||
new CacheResult
|
||||
{
|
||||
lazy val uptodate = headResult.uptodate && tailResult.uptodate
|
||||
val uptodate = headResult.uptodate && tailResult.uptodate
|
||||
def update(outputStream: OutputStream) =
|
||||
{
|
||||
headResult.update(outputStream)
|
||||
|
|
|
|||
|
|
@ -4,19 +4,25 @@ import java.io.File
|
|||
|
||||
object CacheTest// extends Properties("Cache test")
|
||||
{
|
||||
val lengthCache = new File("/tmp/length-cache")
|
||||
val cCache = new File("/tmp/c-cache")
|
||||
|
||||
import Task._
|
||||
import Cache._
|
||||
import FileInfo.hash._
|
||||
def checkFormattable(file: File)
|
||||
def test
|
||||
{
|
||||
val createTask = Task { new File("test") }
|
||||
val lengthTask = createTask map { f => println("File length: " + f.length); f.length }
|
||||
val cached = Cache(lengthTask, new File("/tmp/length-cache"))
|
||||
|
||||
val cTask = (createTask :: cached :: TNil) map { case (file :: len :: HNil) => println("File: " + file + " length: " + len); len :: file :: HNil }
|
||||
val cachedC = Cache(cTask, new File("/tmp/c-cache"))
|
||||
val length = (f: File) => { println("File length: " + f.length); f.length }
|
||||
val cachedLength = cached(lengthCache) ( length )
|
||||
|
||||
try { TaskRunner(cachedC) }
|
||||
val lengthTask = createTask map cachedLength
|
||||
|
||||
val c = (file: File, len: Long) => { println("File: " + file + ", length: " + len); len :: file :: HNil }
|
||||
val cTask = (createTask :: lengthTask :: TNil) map cached(cCache) { case (file :: len :: HNil) => c(file, len) }
|
||||
|
||||
try { TaskRunner(cTask) }
|
||||
catch { case TasksFailed(failures) => failures.foreach(_.exception.printStackTrace) }
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@ class Changed[O](val task: Task[O], val cacheFile: File)(implicit input: InputCa
|
|||
{
|
||||
val clean = Clean(cacheFile)
|
||||
def clear = Task.empty
|
||||
def apply[O2](ifChanged: O => O2, ifUnchanged: O => O2): Task[O2] { type Input = O } =
|
||||
def apply[O2](ifChanged: O => O2, ifUnchanged: O => O2): Task[O2] =
|
||||
task map { value =>
|
||||
val cache =
|
||||
try { OpenResource.fileInputStream(cacheFile)(input.uptodate(value)) }
|
||||
|
|
|
|||
|
|
@ -1,15 +1,29 @@
|
|||
package xsbt
|
||||
|
||||
import metascala.HLists.{HCons => metaHCons, HList => metaHList, HNil => metaHNil}
|
||||
// stripped down version of http://trac.assembla.com/metascala/browser/src/metascala/HLists.scala
|
||||
// Copyright (c) 2009, Jesper Nordenberg
|
||||
// new BSD license, see licenses/MetaScala
|
||||
|
||||
object HLists extends HLists
|
||||
// add an extractor to metascala.HLists and define aliases to the HList classes in the xsbt namespace
|
||||
trait HLists extends NotNull
|
||||
trait HLists
|
||||
{
|
||||
object :: { def unapply[H,T<:HList](list: HCons[H,T]) = Some((list.head,list.tail)) }
|
||||
final val HNil = metaHNil
|
||||
final type ::[H, T <: HList] = metaHCons[H, T]
|
||||
final type HNil = metaHNil
|
||||
final type HList = metaHList
|
||||
final type HCons[H, T <: HList] = metaHCons[H, T]
|
||||
type ::[H, T <: HList] = HCons[H, T]
|
||||
}
|
||||
|
||||
object HNil extends HNil
|
||||
sealed trait HList {
|
||||
type Head
|
||||
type Tail <: HList
|
||||
}
|
||||
sealed class HNil extends HList {
|
||||
type Head = Nothing
|
||||
type Tail = HNil
|
||||
def ::[T](v : T) = HCons(v, this)
|
||||
}
|
||||
|
||||
final case class HCons[H, T <: HList](head : H, tail : T) extends HList {
|
||||
type Head = H
|
||||
type Tail = T
|
||||
def ::[T](v : T) = HCons(v, this)
|
||||
}
|
||||
Binary file not shown.
Loading…
Reference in New Issue