diff --git a/main-command/src/main/scala/sbt/BasicCommands.scala b/main-command/src/main/scala/sbt/BasicCommands.scala index 04e0a60b8..cdcbd32c1 100644 --- a/main-command/src/main/scala/sbt/BasicCommands.scala +++ b/main-command/src/main/scala/sbt/BasicCommands.scala @@ -211,25 +211,23 @@ object BasicCommands { // then we directly evaluate the `() => State` returned by the parser. Otherwise, we // fall back to prefixing the multi commands to the state. // - state.nonMultiCommands.view.flatMap { - case command => - command.nameOption match { - case Some(commandName) if first.startsWith(commandName) => - // A lot of commands expect leading semicolons in their parsers. In order to - // ensure that they are multi-command capable, we strip off any leading spaces. - // Without doing this, we could run simple commands like `set` with the full - // input. This would likely fail because `set` doesn't know how to handle - // semicolons. This is a bit of a hack that is specifically there - // to handle `~` which doesn't require a space before its argument. Any command - // whose parser accepts multi commands without a leading space should be accepted. - // All other commands should be rejected. Note that `alias` is also handled by - // this case. - val commandArgs = - (first.drop(commandName.length).trim :: Nil ::: tail).mkString(";") - parse(commandArgs, command.parser(state)).toOption - case _ => None - } - case _ => None + state.nonMultiCommands.view.flatMap { command => + command.nameOption match { + case Some(commandName) if first.startsWith(commandName) => + // A lot of commands expect leading semicolons in their parsers. In order to + // ensure that they are multi-command capable, we strip off any leading spaces. + // Without doing this, we could run simple commands like `set` with the full + // input. This would likely fail because `set` doesn't know how to handle + // semicolons. This is a bit of a hack that is specifically there + // to handle `~` which doesn't require a space before its argument. Any command + // whose parser accepts multi commands without a leading space should be accepted. + // All other commands should be rejected. Note that `alias` is also handled by + // this case. + val commandArgs = + (first.drop(commandName.length).trim :: Nil ::: tail).mkString(";") + parse(commandArgs, command.parser(state)).toOption + case _ => None + } }.headOption match { case Some(s) => s() case _ => commands ::: state diff --git a/main/src/main/scala/sbt/MainLoop.scala b/main/src/main/scala/sbt/MainLoop.scala index 3f4f48217..0683621ee 100644 --- a/main/src/main/scala/sbt/MainLoop.scala +++ b/main/src/main/scala/sbt/MainLoop.scala @@ -214,12 +214,12 @@ object MainLoop { } Parser.parse( checkCommand, - state.put(Aggregation.suppressShow, true).combinedParser + state.copy(remainingCommands = Nil).put(Aggregation.suppressShow, true).combinedParser ) match { case Right(cmd) => cmd() match { case s if s.remainingCommands.headOption.map(_.commandLine).contains("reload") => - s.remove(Aggregation.suppressShow) + Exec("reload", None, None) +: exec +: state case _ => process() } case Left(_) => process() diff --git a/sbt/src/sbt-test/nio/reload/build.sbt b/sbt/src/sbt-test/nio/reload/build.sbt index 99cf2533a..c143ba056 100644 --- a/sbt/src/sbt-test/nio/reload/build.sbt +++ b/sbt/src/sbt-test/nio/reload/build.sbt @@ -1,4 +1,13 @@ -val foo = taskKey[Unit]("working task") -foo := { println("foo") } +val foo = inputKey[Unit]("working task") +foo := { + val filename = Def.spaceDelimited("").parsed.head + IO.touch(baseDirectory.value / filename) +} + +val exists = inputKey[Unit]("check that the file was written") +exists := { + val filename = Def.spaceDelimited("").parsed.head + assert((baseDirectory.value / filename).exists) +} Global / onChangedBuildSource := ReloadOnSourceChanges diff --git a/sbt/src/sbt-test/nio/reload/changes/broken.sbt b/sbt/src/sbt-test/nio/reload/changes/broken.sbt index 9b0d8d62d..57e15cd57 100644 --- a/sbt/src/sbt-test/nio/reload/changes/broken.sbt +++ b/sbt/src/sbt-test/nio/reload/changes/broken.sbt @@ -1,4 +1,10 @@ -val foo = taskKey[Unit]("broken task") +val foo = inputKey[Unit]("broken task") foo := { throw new IllegalStateException("foo") } +val exists = inputKey[Unit]("check that the file was written") +exists := { + val filename = Def.spaceDelimited("").parsed.head + assert((baseDirectory.value / filename).exists) +} + Global / onChangedBuildSource := ReloadOnSourceChanges diff --git a/sbt/src/sbt-test/nio/reload/changes/working.sbt b/sbt/src/sbt-test/nio/reload/changes/working.sbt index 99cf2533a..c143ba056 100644 --- a/sbt/src/sbt-test/nio/reload/changes/working.sbt +++ b/sbt/src/sbt-test/nio/reload/changes/working.sbt @@ -1,4 +1,13 @@ -val foo = taskKey[Unit]("working task") -foo := { println("foo") } +val foo = inputKey[Unit]("working task") +foo := { + val filename = Def.spaceDelimited("").parsed.head + IO.touch(baseDirectory.value / filename) +} + +val exists = inputKey[Unit]("check that the file was written") +exists := { + val filename = Def.spaceDelimited("").parsed.head + assert((baseDirectory.value / filename).exists) +} Global / onChangedBuildSource := ReloadOnSourceChanges diff --git a/sbt/src/sbt-test/nio/reload/test b/sbt/src/sbt-test/nio/reload/test index 1829bde7f..abfe64f5e 100644 --- a/sbt/src/sbt-test/nio/reload/test +++ b/sbt/src/sbt-test/nio/reload/test @@ -1,9 +1,19 @@ -> foo +> foo bar + +> exists bar $ copy-file changes/broken.sbt build.sbt --> foo +-> foo baz + +-> exists baz $ copy-file changes/working.sbt build.sbt -> foo +> foo baz + +> exists baz + +> foo foo; reload + +> exists foo