mirror of https://github.com/sbt/sbt.git
continuous polling interval now in milliseconds
This commit is contained in:
parent
3922580c58
commit
11c2b2239c
|
|
@ -11,7 +11,7 @@ package sbt
|
|||
import sbt.complete.{DefaultParsers, Parser}
|
||||
|
||||
import Command.applyEffect
|
||||
import Keys.{Analysis,HistoryPath,Logged,ShellPrompt,Watch}
|
||||
import Keys.{Analysis,HistoryPath,Logged,ShellPrompt}
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.JavaConversions._
|
||||
import Function.tupled
|
||||
|
|
@ -197,7 +197,7 @@ object BuiltinCommands
|
|||
// TODO: nest
|
||||
def continuous =
|
||||
Command.single(ContinuousExecutePrefix, Help(continuousBriefHelp) ) { (s, arg) =>
|
||||
withAttribute(s, Watch.key, "Continuous execution not configured.") { w =>
|
||||
withAttribute(s, Watched.Configuration, "Continuous execution not configured.") { w =>
|
||||
val repeat = ContinuousExecutePrefix + (if(arg.startsWith(" ")) arg else " " + arg)
|
||||
Watched.executeContinuously(w, s, arg, repeat)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,13 +75,14 @@ object Project extends Init[Scope]
|
|||
val ref = ProjectRef(uri, id)
|
||||
val project = Load.getProject(structure.units, uri, id)
|
||||
logger(s).info("Set current project to " + id + " (in build " + uri +")")
|
||||
def get[T](k: SettingKey[T]): Option[T] = k in ref get structure.data
|
||||
|
||||
val data = structure.data
|
||||
val historyPath = HistoryPath in ref get data flatMap identity
|
||||
val prompt = ShellPrompt in ref get data
|
||||
val commands = (Commands in ref get data).toList.flatten[Command].map(_ tag (ProjectCommand, true))
|
||||
val historyPath = get(HistoryPath) flatMap identity
|
||||
val prompt = get(ShellPrompt)
|
||||
val watched = get(Watch)
|
||||
val commands = get(Commands).toList.flatten[Command].map(_ tag (ProjectCommand, true))
|
||||
val newProcessors = commands ++ BuiltinCommands.removeTagged(s.processors, ProjectCommand)
|
||||
val newAttrs = s.attributes.put(Watch.key, makeWatched(data, ref, project)).put(HistoryPath.key, historyPath)
|
||||
val newAttrs = setCond(Watched.Configuration, watched, s.attributes).put(HistoryPath.key, historyPath)
|
||||
s.copy(attributes = setCond(ShellPrompt.key, prompt, newAttrs), processors = newProcessors)
|
||||
}
|
||||
def setCond[T](key: AttributeKey[T], vopt: Option[T], attributes: AttributeMap): AttributeMap =
|
||||
|
|
@ -89,17 +90,6 @@ object Project extends Init[Scope]
|
|||
def makeSettings(settings: Seq[Setting[_]], delegates: Scope => Seq[Scope], scopeLocal: ScopedKey[_] => Seq[Setting[_]]) =
|
||||
translateUninitialized( make(settings)(delegates, scopeLocal) )
|
||||
|
||||
def makeWatched(data: Settings[Scope], ref: ProjectRef, project: Project): Watched =
|
||||
{
|
||||
def getWatch(ref: ProjectRef) = Watch in ref get data
|
||||
getWatch(ref) match
|
||||
{
|
||||
case Some(currentWatch) =>
|
||||
val subWatches = project.uses flatMap { p => getWatch(p) }
|
||||
Watched.multi(currentWatch, subWatches)
|
||||
case None => Watched.empty
|
||||
}
|
||||
}
|
||||
def display(scoped: ScopedKey[_]): String = Scope.display(scoped.scope, scoped.key.label)
|
||||
def display(ref: ProjectRef): String = "(" + (ref.uri map (_.toString) getOrElse "<this>") + ")" + (ref.id getOrElse "<root>")
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,17 @@ package sbt
|
|||
|
||||
import CommandSupport.{ClearOnFailure,FailureWall}
|
||||
import annotation.tailrec
|
||||
import java.io.File
|
||||
|
||||
trait Watched
|
||||
{
|
||||
/** A `PathFinder` that determines the files watched when an action is run with a preceeding ~ when this is the current
|
||||
* project. This project does not need to include the watched paths for projects that this project depends on.*/
|
||||
def watchPaths: PathFinder = Path.emptyPathFinder
|
||||
def watchPaths(s: State): Seq[File] = Nil
|
||||
def terminateWatch(key: Int): Boolean = Watched.isEnter(key)
|
||||
/** The time in milliseconds between checking for changes. The actual time between the last change made to a file and the
|
||||
* execution time is between `pollInterval` and `pollInterval*2`.*/
|
||||
def pollInterval: Int = Watched.PollDelayMillis
|
||||
}
|
||||
|
||||
object Watched
|
||||
|
|
@ -21,24 +25,25 @@ object Watched
|
|||
def multi(base: Watched, paths: Seq[Watched]): Watched =
|
||||
new AWatched
|
||||
{
|
||||
override val watchPaths = (base.watchPaths /: paths)(_ +++ _.watchPaths)
|
||||
override def watchPaths(s: State) = (base.watchPaths(s) /: paths)(_ ++ _.watchPaths(s))
|
||||
override def terminateWatch(key: Int): Boolean = base.terminateWatch(key)
|
||||
override val pollInterval = (base +: paths).map(_.pollInterval).min
|
||||
}
|
||||
def empty: Watched = new AWatched
|
||||
|
||||
val PollDelaySeconds = 1
|
||||
val PollDelayMillis = 500
|
||||
def isEnter(key: Int): Boolean = key == 10 || key == 13
|
||||
|
||||
def executeContinuously(watched: Watched, s: State, next: String, repeat: String): State =
|
||||
{
|
||||
@tailrec def shouldTerminate: Boolean = (System.in.available > 0) && (watched.terminateWatch(System.in.read()) || shouldTerminate)
|
||||
val sourcesFinder = watched.watchPaths
|
||||
val sourcesFinder = Path.finder { watched watchPaths s }
|
||||
val watchState = s get ContinuousState getOrElse WatchState.empty
|
||||
|
||||
if(watchState.count > 0)
|
||||
System.out.println(watchState.count + ". Waiting for source changes... (press enter to interrupt)")
|
||||
|
||||
val (triggered, newWatchState) = SourceModificationWatch.watch(sourcesFinder, PollDelaySeconds, watchState)(shouldTerminate)
|
||||
val (triggered, newWatchState) = SourceModificationWatch.watch(sourcesFinder, watched.pollInterval, watchState)(shouldTerminate)
|
||||
|
||||
if(triggered)
|
||||
(ClearOnFailure :: next :: FailureWall :: repeat :: s).put(ContinuousState, newWatchState)
|
||||
|
|
@ -49,4 +54,5 @@ object Watched
|
|||
}
|
||||
}
|
||||
val ContinuousState = AttributeKey[WatchState]("watch state")
|
||||
val Configuration = AttributeKey[Watched]("watched-configuration")
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ package sbt
|
|||
|
||||
object SourceModificationWatch
|
||||
{
|
||||
@tailrec def watch(sourcesFinder: PathFinder, pollDelaySec: Int, state: WatchState)(terminationCondition: => Boolean): (Boolean, WatchState) =
|
||||
@tailrec def watch(sourcesFinder: PathFinder, pollDelayMillis: Int, state: WatchState)(terminationCondition: => Boolean): (Boolean, WatchState) =
|
||||
{
|
||||
import state._
|
||||
|
||||
|
|
@ -30,11 +30,11 @@ object SourceModificationWatch
|
|||
(true, newState)
|
||||
else
|
||||
{
|
||||
Thread.sleep(pollDelaySec * 1000)
|
||||
Thread.sleep(pollDelayMillis)
|
||||
if(terminationCondition)
|
||||
(false, newState)
|
||||
else
|
||||
watch(sourcesFinder, pollDelaySec, newState)(terminationCondition)
|
||||
watch(sourcesFinder, pollDelayMillis, newState)(terminationCondition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue