Skip to content

Commit

Permalink
Disable selection execution for run that occurs when enter is pressed…
Browse files Browse the repository at this point in the history
… during watch (#4149)

No tests for now, since our integration test suite doesn't easily
support feeding stdin to the mill subprocess
  • Loading branch information
lihaoyi authored Dec 17, 2024
1 parent 2c6157d commit 8adb242
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 11 deletions.
5 changes: 4 additions & 1 deletion runner/src/mill/runner/MillMain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ object MillMain {
watch = config.watch.value,
streams = streams,
setIdle = setIdle,
evaluate = (prevState: Option[RunnerState]) => {
evaluate = (enterKeyPressed: Boolean, prevState: Option[RunnerState]) => {
adjustJvmProperties(userSpecifiedProperties, initialSystemProperties)

withOutLock(
Expand All @@ -256,6 +256,9 @@ object MillMain {
colored = colored,
colors = colors
)) { logger =>
// Enter key pressed, removing mill-selective-execution.json to
// ensure all tasks re-run even though no inputs may have changed
if (enterKeyPressed) os.remove(out / OutFiles.millSelectiveExecution)
SystemStreams.withStreams(logger.systemStreams) {
tailManager.withOutErr(logger.outputStream, logger.errorStream) {
new MillBuildBootstrap(
Expand Down
26 changes: 16 additions & 10 deletions runner/src/mill/runner/Watching.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ object Watching {
watch: Boolean,
streams: SystemStreams,
setIdle: Boolean => Unit,
evaluate: Option[T] => Result[T],
evaluate: (Boolean, Option[T]) => Result[T],
colors: Colors
): (Boolean, T) = {
var prevState: Option[T] = None
var enterKeyPressed = false
while (true) {
val Result(watchables, errorOpt, result) = evaluate(prevState)
val Result(watchables, errorOpt, result) = evaluate(enterKeyPressed, prevState)
prevState = Some(result)
errorOpt.foreach(streams.err.println)
if (ringBell) {
Expand All @@ -42,8 +43,9 @@ object Watching {
}

val alreadyStale = watchables.exists(!_.validate())
enterKeyPressed = false
if (!alreadyStale) {
Watching.watchAndWait(streams, setIdle, streams.in, watchables, colors)
enterKeyPressed = Watching.watchAndWait(streams, setIdle, streams.in, watchables, colors)
}
}
???
Expand All @@ -55,7 +57,7 @@ object Watching {
stdin: InputStream,
watched: Seq[Watchable],
colors: Colors
): Unit = {
): Boolean = {
setIdle(true)
val watchedPaths = watched.collect { case p: Watchable.Path => p.p.path }
val watchedValues = watched.size - watchedPaths.size
Expand All @@ -68,21 +70,25 @@ object Watching {
).toString
)

statWatchWait(watched, stdin)
val enterKeyPressed = statWatchWait(watched, stdin)
setIdle(false)
enterKeyPressed
}

def statWatchWait(watched: Seq[Watchable], stdin: InputStream): Unit = {
// Returns `true` if enter key is pressed to re-run tasks explicitly
def statWatchWait(watched: Seq[Watchable], stdin: InputStream): Boolean = {
val buffer = new Array[Byte](4 * 1024)

@tailrec def statWatchWait0(): Unit = {
@tailrec def statWatchWait0(): Boolean = {
if (watched.forall(_.validate())) {
if (lookForEnterKey()) ()
else {
if (lookForEnterKey()) {
mill.main.client.DebugLog.println("ENTER KEY DETECTED")
true
} else {
Thread.sleep(100)
statWatchWait0()
}
}
} else false
}

@tailrec def lookForEnterKey(): Boolean = {
Expand Down

0 comments on commit 8adb242

Please sign in to comment.