From a3c34c6c0a76948fe56ecf990e9defb18dfbf6d6 Mon Sep 17 00:00:00 2001 From: Michael Stringer Date: Tue, 3 Oct 2017 10:30:06 +0100 Subject: [PATCH] Add system property to revert to old polling fs watcher This adds a sbt.watch.mode system property that if set to 'polling' will use PollingWatchService instead of WatchServiceAdapter (nio). On macOS this will default to 'polling' and on all others 'nio'. This is a temporary workaround for users affected by #3527 --- main-command/src/main/scala/sbt/Watched.scala | 29 ++++++++++++++----- main/src/main/scala/sbt/Defaults.scala | 3 +- notes/1.0.3/watch.md | 26 +++++++++++++++++ 3 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 notes/1.0.3/watch.md diff --git a/main-command/src/main/scala/sbt/Watched.scala b/main-command/src/main/scala/sbt/Watched.scala index 0d24e18c4..fa1dee03f 100644 --- a/main-command/src/main/scala/sbt/Watched.scala +++ b/main-command/src/main/scala/sbt/Watched.scala @@ -7,18 +7,19 @@ package sbt -import BasicCommandStrings.ClearOnFailure -import State.FailureWall -import annotation.tailrec import java.io.File import java.nio.file.FileSystems -import scala.concurrent.duration._ - -import sbt.io.{ AllPassFilter, NothingFilter, FileFilter, WatchService } +import sbt.BasicCommandStrings.ClearOnFailure +import sbt.State.FailureWall import sbt.internal.io.{ Source, SourceModificationWatch, WatchState } import sbt.internal.util.AttributeKey import sbt.internal.util.Types.const +import sbt.io._ + +import scala.annotation.tailrec +import scala.concurrent.duration._ +import scala.util.Properties trait Watched { @@ -39,7 +40,7 @@ trait Watched { private[sbt] def triggeredMessage(s: WatchState): String = Watched.defaultTriggeredMessage(s) /** The `WatchService` to use to monitor the file system. */ - private[sbt] def watchService(): WatchService = FileSystems.getDefault.newWatchService() + private[sbt] def watchService(): WatchService = Watched.createWatchService() } object Watched { @@ -125,4 +126,18 @@ object Watched { AttributeKey[WatchState]("watch state", "Internal: tracks state for continuous execution.") val Configuration = AttributeKey[Watched]("watched-configuration", "Configures continuous execution.") + + def createWatchService(): WatchService = { + sys.props.get("sbt.watch.mode") match { + case Some("polling") => + new PollingWatchService(PollDelay) + case Some("nio") => + FileSystems.getDefault.newWatchService() + case _ if Properties.isMac => + // WatchService is slow on macOS - use old polling mode + new PollingWatchService(PollDelay) + case _ => + FileSystems.getDefault.newWatchService() + } + } } diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 6fa48bcd9..16122e720 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -9,7 +9,6 @@ package sbt import Def.{ Initialize, ScopedKey, Setting, SettingsDefinition } import java.io.{ File, PrintWriter } -import java.nio.file.FileSystems import java.net.{ URI, URL } import java.util.Optional import java.util.concurrent.{ TimeUnit, Callable } @@ -251,7 +250,7 @@ object Defaults extends BuildCommon { parallelExecution :== true, pollInterval :== new FiniteDuration(500, TimeUnit.MILLISECONDS), watchService :== { () => - FileSystems.getDefault.newWatchService + Watched.createWatchService() }, logBuffered :== false, commands :== Nil, diff --git a/notes/1.0.3/watch.md b/notes/1.0.3/watch.md new file mode 100644 index 000000000..ff751fdf9 --- /dev/null +++ b/notes/1.0.3/watch.md @@ -0,0 +1,26 @@ +### Fixes with compatibility implications + +### Improvements + +- Add `sbt.watch.mode` system property to allow switching back to old polling behaviour for watch. See below for more details. [#3597][3597] by [@stringbean][@stringbean] + +### Bug fixes + +#### Alternative watch mode + +sbt 1.0.0 introduced a new mechanism for watching for source changes based on the NIO `WatchService` in Java 1.7. On +some platforms (namely macOS) this has led to long delays before changes are picked up. An alternative `WatchService` +for these platforms is planned for sbt 1.1.0 ([#3527][3527]), in the meantime an option to select which watch service +has been added. + +The new `sbt.watch.mode` JVM flag has been added with the following supported values: + +- `polling`: (default for macOS) poll the filesystem for changes (mechanism used in sbt 0.13). +- `nio` (default for other platforms): use the NIO based `WatchService`. + +If you are experiencing long delays on a non-macOS machine then try adding `-Dsbt.watch.mode=polling` to your sbt +options. + +[@stringbean]: https://github.com/stringbean +[3527]: https://github.com/sbt/sbt/issues/3527 +[3597]: https://github.com/sbt/sbt/pull/3597