From 09051773461b98d374d1b46dd0a2caa57768ab30 Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Thu, 15 Jun 2017 22:38:53 -0400 Subject: add sbt-resolver like restart feature --- README.md | 5 +++++ cbt | 16 ++++++++++++++++ examples/restart/Readme.md | 10 ++++++++++ examples/restart/build/build.scala | 4 ++++ examples/restart/src/Main.scala | 6 ++++++ stage1/Stage1Lib.scala | 15 +++++++++++++++ stage2/BasicBuild.scala | 13 +++++++++++++ 7 files changed, 69 insertions(+) create mode 100644 examples/restart/Readme.md create mode 100644 examples/restart/build/build.scala create mode 100644 examples/restart/src/Main.scala diff --git a/README.md b/README.md index 94aa2ab..90dd845 100644 --- a/README.md +++ b/README.md @@ -226,6 +226,11 @@ To also clear the screen on each run use: $ cbt loop clear run ``` +To call and restart the main method on file change (like sbt-revolver) +``` +$ cbt direct loop restart +``` + ### Adding tests The simplest way to add tests is putting a few assertions into the previously diff --git a/cbt b/cbt index 4a5b736..e2014ec 100755 --- a/cbt +++ b/cbt @@ -290,6 +290,7 @@ stage1 () { USER_PRESSED_CTRL_C=130 CBT_LOOP_FILE="$CWD/target/.cbt-loop.tmp" +CBT_KILL_FILE="$CWD/target/.cbt-kill.tmp" if [ $loop -eq 0 ]; then which fswatch >/dev/null 2>/dev/null export fswatch_installed=$? @@ -305,6 +306,9 @@ while true; do if [ -f "$CBT_LOOP_FILE" ]; then rm "$CBT_LOOP_FILE" fi + if [ -f "$CBT_KILL_FILE" ]; then + rm "$CBT_KILL_FILE" + fi stage1 "$@" if [ ! $loop -eq 0 ] || [ $exitCode -eq $USER_PRESSED_CTRL_C ]; then log "not looping, exiting" "$@" @@ -316,6 +320,10 @@ while true; do files= if [ -f "$CBT_LOOP_FILE" ]; then files=($(sort "$CBT_LOOP_FILE")) + fi + pids= + if [ -f "$CBT_KILL_FILE" ]; then + pids=($(cat "$CBT_KILL_FILE")) # FIXME: should we uniq here? #rm "$CBT_LOOP_FILE" fi echo "" @@ -326,6 +334,14 @@ while true; do fi done fswatch --one-event "${files[@]}" + for pid in "${pids[@]}"; do + if [ $pid == "" ]; then + echo "warning: empty pid found in pid kill list" 1>&2 + else + log "killing process $pid" + kill -KILL $pid + fi + done fi done diff --git a/examples/restart/Readme.md b/examples/restart/Readme.md new file mode 100644 index 0000000..e4bf1b5 --- /dev/null +++ b/examples/restart/Readme.md @@ -0,0 +1,10 @@ +This example's main method simply prints the current process id. +This can be used to experiment with cbt's restart feature +(the equivalent to sbt-revolver). + +``` +cbt direct loop restart +``` + +starts the main method in a separate process and kills it, when +a change in project, build file or cbt is detected. diff --git a/examples/restart/build/build.scala b/examples/restart/build/build.scala new file mode 100644 index 0000000..a18f951 --- /dev/null +++ b/examples/restart/build/build.scala @@ -0,0 +1,4 @@ +import cbt._ +class Build(val context: Context) extends BaseBuild{ + override def dependencies = super.dependencies :+ libraries.cbt.process +} \ No newline at end of file diff --git a/examples/restart/src/Main.scala b/examples/restart/src/Main.scala new file mode 100644 index 0000000..1c03832 --- /dev/null +++ b/examples/restart/src/Main.scala @@ -0,0 +1,6 @@ +object Main extends App { + while(true){ + Thread.sleep(1000) + println( "process " + cbt.process.currentProcessId + " is still running" ) + } +} diff --git a/stage1/Stage1Lib.scala b/stage1/Stage1Lib.scala index ab95a41..89e52b6 100644 --- a/stage1/Stage1Lib.scala +++ b/stage1/Stage1Lib.scala @@ -417,6 +417,21 @@ ${sourceFiles.sorted.mkString(" \\\n")} StandardOpenOption.APPEND ) } + + /** + add process id to a cbt internal list of processes to kill + when looping after a file change + */ + def addProcessIdToKillList(cwd: File, processId: Int) = { + val file = cwd / "target/.cbt-kill.tmp" + file.createNewFile + lib.write( + file, + processId.toString + "\n", + StandardOpenOption.APPEND + ) + } + def cached[T]( targetDirectory: File, inputLastModified: Long )( action: () => T ): (Option[T],Long) = { val t = targetDirectory val start = System.currentTimeMillis diff --git a/stage2/BasicBuild.scala b/stage2/BasicBuild.scala index e41545b..3a9c958 100644 --- a/stage2/BasicBuild.scala +++ b/stage2/BasicBuild.scala @@ -327,6 +327,19 @@ trait BaseBuild extends BuildInterface with DependencyImplementation with SbtDep waitFor() } + /** currently only produces output when run via cbt direct */ + def restart: Int = { + val pid = restart( mainClassOrFail.getName, context.args ) + System.err.print("started process with pid: ") + pid + } + + def restart( className: String, args: Seq[String] ): Int = { + val ( pid, waitFor, destroy ) = runForked( mainClassOrFail.getName, context.args ) + lib.addProcessIdToKillList( context.cwd, pid ) + pid + } + protected def runForkedHandles = runForked( mainClassOrFail.getName, context.args ) def runForked( className: String, args: Seq[String] ): ( Int, () => ExitCode, () => ExitCode ) = -- cgit v1.2.3