Skip to content

Draft: Implement watching file paths via oslib.watch #5068

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
May 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8ec73a8
WIP: fs-watching
arturaz May 5, 2025
7a2eace
Merge remote-tracking branch 'upstream/main' into improvement/fs-watc…
arturaz May 5, 2025
b4af95f
[autofix.ci] apply automated fixes
autofix-ci[bot] May 5, 2025
e7faaa8
fixes
arturaz May 6, 2025
1000593
Merge remote-tracking branch 'upstream/main' into improvement/fs-watc…
arturaz May 6, 2025
4175938
Merge remote-tracking branch 'origin/improvement/fs-watching' into im…
arturaz May 6, 2025
3e7c22c
Forward porting from 0.12.x branch.
arturaz May 8, 2025
51cbab5
[autofix.ci] apply automated fixes
autofix-ci[bot] May 8, 2025
895c077
Merge remote-tracking branch 'upstream/main' into improvement/fs-watc…
arturaz May 9, 2025
14b94ef
Merge remote-tracking branch 'refs/remotes/origin/improvement/fs-watc…
arturaz May 9, 2025
c331c46
[autofix.ci] apply automated fixes
autofix-ci[bot] May 9, 2025
2726072
Catch if `writeToWatchLog` tries to write to a closed file.
arturaz May 8, 2025
8b76abf
Merge remote-tracking branch 'refs/remotes/origin/improvement/fs-watc…
arturaz May 9, 2025
9021c19
CI test debug
arturaz May 13, 2025
2dcf557
CI test debug
arturaz May 13, 2025
dfbba1f
debug watch tests with sleeps
arturaz May 13, 2025
1b797e9
Move stale checking after we start the watch
arturaz May 13, 2025
ad139ab
[autofix.ci] apply automated fixes
autofix-ci[bot] May 13, 2025
69390dd
Refactor setIdle
arturaz May 13, 2025
2a84a72
Make tests more robust.
arturaz May 13, 2025
50bfa30
Merge remote-tracking branch 'refs/remotes/origin/improvement/fs-watc…
arturaz May 13, 2025
a4de281
[autofix.ci] apply automated fixes
autofix-ci[bot] May 13, 2025
35deeed
Revert `run-tests.yml`
arturaz May 13, 2025
8851638
Merge remote-tracking branch 'refs/remotes/origin/improvement/fs-watc…
arturaz May 13, 2025
46990ff
Code review changes.
arturaz May 19, 2025
06760b5
Merge remote-tracking branch 'upstream/main' into improvement/fs-watc…
arturaz May 19, 2025
5e2d445
[autofix.ci] apply automated fixes
autofix-ci[bot] May 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions core/api/src/mill/api/Watchable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@ package mill.api
*/
private[mill] sealed trait Watchable
private[mill] object Watchable {

/**
* Watched path, can be watched via polling or via a notification system.
*
* @param p the path to watch
* @param quick if true, only watch file attributes
* @param signature the initial hash of the path contents
*/
case class Path(p: java.nio.file.Path, quick: Boolean, signature: Int) extends Watchable

/**
* Watched expression, can only be watched via polling.
*
* @param f the expression to watch, returns some sort of hash
* @param signature the initial hash from the first invocation of the expression
* @param pretty human-readable name
*/
case class Value(f: () => Long, signature: Long, pretty: String) extends Watchable
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,9 @@ trait WatchTests extends UtestIntegrationTestSuite {
val expectedShows0 = mutable.Buffer.empty[String]
val res = f(expectedOut, expectedErr, expectedShows0)
val (shows, out) = res.out.linesIterator.toVector.partition(_.startsWith("\""))
val err = res.err.linesIterator.toVector
.filter(!_.contains("Compiling compiler interface..."))
.filter(!_.contains("Watching for changes"))
.filter(!_.contains("[info] compiling"))
.filter(!_.contains("[info] done compiling"))
.filter(!_.contains("mill-daemon/ exitCode file not found"))
val err = res.err.linesIterator.toVector.filter(s =>
s.startsWith("Setting up ") || s.startsWith("Running ")
)

assert(out == expectedOut)

Expand Down
4 changes: 3 additions & 1 deletion mill-build/src/millbuild/Deps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ object Deps {
val junitInterface = mvn"com.github.sbt:junit-interface:0.13.3"
val commonsIo = mvn"commons-io:commons-io:2.18.0"
val log4j2Core = mvn"org.apache.logging.log4j:log4j-core:2.24.3"
val osLib = mvn"com.lihaoyi::os-lib:0.11.5-M8"
val osLibVersion = "0.11.5-M8"
val osLib = mvn"com.lihaoyi::os-lib:$osLibVersion"
val osLibWatch = mvn"com.lihaoyi::os-lib-watch:$osLibVersion"
val pprint = mvn"com.lihaoyi::pprint:0.9.0"
val mainargs = mvn"com.lihaoyi::mainargs:0.7.6"
val millModuledefsVersion = "0.11.4"
Expand Down
1 change: 1 addition & 0 deletions runner/daemon/package.mill
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ object `package` extends MillPublishScalaModule {
def mvnDeps = Seq(
Deps.sourcecode,
Deps.osLib,
Deps.osLibWatch,
Deps.mainargs,
Deps.upickle,
Deps.pprint,
Expand Down
2 changes: 1 addition & 1 deletion runner/daemon/src/mill/daemon/MillBuildBootstrap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ class MillBuildBootstrap(
// look at the `moduleWatched` of one frame up (`prevOuterFrameOpt`),
// and not the `moduleWatched` from the current frame (`prevFrameOpt`)
val moduleWatchChanged =
prevOuterFrameOpt.exists(_.moduleWatched.exists(w => !Watching.validate(w)))
prevOuterFrameOpt.exists(_.moduleWatched.exists(w => !Watching.haveNotChanged(w)))

val classLoader = if (runClasspathChanged || moduleWatchChanged) {
// Make sure we close the old classloader every time we create a new
Expand Down
5 changes: 5 additions & 0 deletions runner/daemon/src/mill/daemon/MillCliConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ case class MillCliConfig(
doc = """Watch and re-run the given tasks when when their inputs change."""
)
watch: Flag = Flag(),
@arg(
name = "notify-watch",
doc = "Use filesystem based file watching instead of polling based one (defaults to true)."
)
watchViaFsNotify: Boolean = true,
@arg(
short = 's',
doc =
Expand Down
17 changes: 10 additions & 7 deletions runner/daemon/src/mill/daemon/MillMain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ import mill.api.internal.{BspServerResult, internal}
import mill.api.{Logger, MillException, Result, SystemStreams}
import mill.bsp.BSP
import mill.client.lock.Lock
import mill.constants.{OutFiles, DaemonFiles, Util}
import mill.{api, define}
import mill.constants.{DaemonFiles, OutFiles, Util}
import mill.define.BuildCtx
import mill.internal.{Colors, MultiStream, PromptLogger}
import mill.server.Server
import mill.util.BuildInfo
import mill.{api, define}

import java.io.{InputStream, PipedInputStream, PrintStream}
import java.lang.reflect.InvocationTargetException
import java.util.Locale
import java.util.concurrent.locks.ReentrantLock
import scala.collection.immutable
import scala.jdk.CollectionConverters.*
import scala.util.{Properties, Using}
import scala.util.control.NonFatal
import scala.util.{Properties, Using}

@internal
object MillMain {
Expand Down Expand Up @@ -344,9 +344,13 @@ object MillMain {
if (config.watch.value) os.remove(out / OutFiles.millSelectiveExecution)
Watching.watchLoop(
ringBell = config.ringBell.value,
watch = config.watch.value,
watch = Option.when(config.watch.value)(Watching.WatchArgs(
setIdle = setIdle,
colors,
useNotify = config.watchViaFsNotify,
daemonDir = daemonDir
)),
streams = streams,
setIdle = setIdle,
evaluate = (enterKeyPressed: Boolean, prevState: Option[RunnerState]) => {
adjustJvmProperties(userSpecifiedProperties, initialSystemProperties)
runMillBootstrap(
Expand All @@ -356,8 +360,7 @@ object MillMain {
streams,
config.leftoverArgs.value.mkString(" ")
)
},
colors = colors
}
)
}
}
Expand Down
Loading
Loading