mirror of https://github.com/sbt/sbt.git
117 lines
3.9 KiB
Scala
117 lines
3.9 KiB
Scala
/* sbt -- Simple Build Tool
|
|
* Copyright 2010 Mark Harrah
|
|
*/
|
|
package sbt
|
|
package std
|
|
|
|
import java.io.{InputStream, IOException, OutputStream, Reader, Writer}
|
|
import java.io.{BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter, PrintWriter}
|
|
import java.io.{Closeable, File, FileInputStream, FileOutputStream, InputStreamReader, OutputStreamWriter}
|
|
|
|
import Path._
|
|
|
|
sealed trait TaskStreams
|
|
{
|
|
def default = outID
|
|
def outID = "out"
|
|
def errorID = "err"
|
|
|
|
def readText(a: Task[_], sid: String = default, update: Boolean = true): Task[BufferedReader]
|
|
def readBinary(a: Task[_], sid: String = default, update: Boolean = true): Task[BufferedInputStream]
|
|
|
|
final def readText(a: Task[_], sid: Option[String], update: Boolean): Task[BufferedReader] =
|
|
readText(a, getID(sid), update)
|
|
|
|
final def readBinary(a: Task[_], sid: Option[String], update: Boolean): Task[BufferedInputStream] =
|
|
readBinary(a, getID(sid), update)
|
|
|
|
def text(sid: String = default): PrintWriter
|
|
def binary(sid: String = default): BufferedOutputStream
|
|
|
|
// default logger
|
|
final lazy val log: Logger = log(default)
|
|
def log(sid: String): Logger
|
|
|
|
private[this] def getID(s: Option[String]) = s getOrElse default
|
|
}
|
|
private[sbt] sealed trait ManagedTaskStreams extends TaskStreams
|
|
{
|
|
def open()
|
|
def close()
|
|
}
|
|
|
|
sealed trait Streams
|
|
{
|
|
def apply(a: Task[_], update: Boolean = true): ManagedTaskStreams
|
|
}
|
|
object Streams
|
|
{
|
|
private[this] val closeQuietly = (c: Closeable) => try { c.close() } catch { case _: IOException => () }
|
|
|
|
def multi[Owner](bases: Owner => File, taskOwner: Task[_] => Option[Owner], mkLogger: (Task[_], PrintWriter) => Logger): Streams =
|
|
{
|
|
val taskDirectory = (t: Task[_]) => taskOwner(t) map bases getOrElse error("Cannot get streams for task '" + name(t) + "' with no owner.")
|
|
apply(taskDirectory, mkLogger)
|
|
}
|
|
|
|
def apply(taskDirectory: Task[_] => File, mkLogger: (Task[_], PrintWriter) => Logger): Streams = new Streams { streams =>
|
|
|
|
def apply(a: Task[_], update: Boolean): ManagedTaskStreams = new ManagedTaskStreams {
|
|
private[this] var opened: List[Closeable] = Nil
|
|
private[this] var closed = false
|
|
|
|
def readText(a: Task[_], sid: String = default, update: Boolean = true): Task[BufferedReader] =
|
|
maybeUpdate(a, readText0(a, sid), update)
|
|
|
|
def readBinary(a: Task[_], sid: String = default, update: Boolean = true): Task[BufferedInputStream] =
|
|
maybeUpdate(a, readBinary0(a, sid), update)
|
|
|
|
def text(sid: String = default): PrintWriter =
|
|
make(a, sid)(f => new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), IO.defaultCharset))) )
|
|
|
|
def binary(sid: String = default): BufferedOutputStream =
|
|
make(a, sid)(f => new BufferedOutputStream(new FileOutputStream(f)))
|
|
|
|
def log(sid: String): Logger = mkLogger(a, text(sid))
|
|
|
|
def make[T <: Closeable](a: Task[_], sid: String)(f: File => T): T = synchronized {
|
|
checkOpen()
|
|
val file = taskDirectory(a) / sid
|
|
IO.touch(file)
|
|
val t = f( file )
|
|
opened ::= t
|
|
t
|
|
}
|
|
|
|
def readText0(a: Task[_], sid: String): BufferedReader =
|
|
make(a, sid)(f => new BufferedReader(new InputStreamReader(new FileInputStream(f), IO.defaultCharset)) )
|
|
|
|
def readBinary0(a: Task[_], sid: String): BufferedInputStream =
|
|
make(a, sid)(f => new BufferedInputStream(new FileInputStream(f)))
|
|
|
|
def maybeUpdate[T](base: Task[_], result: => T, update: Boolean) =
|
|
{
|
|
def basic(a: Action[T]) = Task(Info(), a)
|
|
val main = Pure(result _)
|
|
val act = if(update) DependsOn(basic(main), base :: Nil) else main
|
|
basic(act)
|
|
}
|
|
|
|
def open() {}
|
|
|
|
def close(): Unit = synchronized {
|
|
if(!closed)
|
|
{
|
|
closed = true
|
|
opened foreach closeQuietly
|
|
}
|
|
}
|
|
def checkOpen(): Unit = synchronized {
|
|
if(closed) error("Streams for '" + name(a) + "' have been closed.")
|
|
}
|
|
}
|
|
}
|
|
|
|
def name(a: Task[_]): String = a.info.name getOrElse anonName(a)
|
|
def anonName(a: Task[_]) = "anon-" + java.lang.Integer.toString(java.lang.System.identityHashCode(a), 36)
|
|
} |