From 4cd6e6036061f35e82336b7c6303ca24163f5200 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Tue, 1 Mar 2011 09:44:45 -0500 Subject: [PATCH] add 'full' option to 'reboot' that cleans project/boot before restarting --- launch/Launch.scala | 17 ++++++++++++++--- .../src/main/java/xsbti/FullReload.java | 8 ++++++++ .../interface/src/main/java/xsbti/Launcher.java | 5 +++++ .../interface/src/main/java/xsbti/Manage.java | 6 ++++++ main/CommandSupport.scala | 10 +++++++--- main/Main.scala | 6 ++++-- main/State.scala | 2 ++ 7 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 launch/interface/src/main/java/xsbti/Manage.java diff --git a/launch/Launch.scala b/launch/Launch.scala index 74caf83dc..5bbd0deb1 100644 --- a/launch/Launch.scala +++ b/launch/Launch.scala @@ -51,7 +51,17 @@ object Launch val appConfig: xsbti.AppConfiguration = new AppConfiguration(toArray(arguments), workingDirectory, appProvider) val main = appProvider.newMain() - main.run(appConfig) + try { main.run(appConfig) } + catch { case e: xsbti.FullReload => if(e.clean) delete(launcher.bootDirectory); throw e } + } + private[this] def delete(f: File) + { + if(f.isDirectory) + { + val fs = f.listFiles() + if(fs ne null) fs foreach delete + } + if(f.exists) f.delete() } final def launch(run: RunConfiguration => xsbti.MainResult)(config: RunConfiguration) { @@ -68,7 +78,7 @@ final class RunConfiguration(val scalaVersion: String, val app: xsbti.Applicatio import BootConfiguration.{appDirectoryName, baseDirectoryName, ScalaDirectoryName, TestLoadScalaClasses} class Launch private[xsbt](val bootDirectory: File, val ivyOptions: IvyOptions) extends xsbti.Launcher { - import ivyOptions.{cacheDirectory, classifiers, repositories} + import ivyOptions.{classifiers, repositories} bootDirectory.mkdirs private val scalaProviders = new Cache[String, ScalaProvider](new ScalaProvider(_)) def getScala(version: String): xsbti.ScalaProvider = scalaProviders(version) @@ -77,13 +87,14 @@ class Launch private[xsbt](val bootDirectory: File, val ivyOptions: IvyOptions) val updateLockFile = new File(bootDirectory, "sbt.boot.lock") def globalLock: xsbti.GlobalLock = Locks + def cacheDirectory = ivyOptions.cacheDirectory.orNull class ScalaProvider(val version: String) extends xsbti.ScalaProvider with Provider { def launcher: xsbti.Launcher = Launch.this def parentLoader = topLoader - lazy val configuration = new UpdateConfiguration(bootDirectory, cacheDirectory, version, repositories) + lazy val configuration = new UpdateConfiguration(bootDirectory, ivyOptions.cacheDirectory, version, repositories) lazy val libDirectory = new File(configuration.bootDirectory, baseDirectoryName(version)) lazy val scalaHome = new File(libDirectory, ScalaDirectoryName) def compilerJar = new File(scalaHome,CompilerModuleName + ".jar") diff --git a/launch/interface/src/main/java/xsbti/FullReload.java b/launch/interface/src/main/java/xsbti/FullReload.java index eb890ccfb..8f94be65e 100644 --- a/launch/interface/src/main/java/xsbti/FullReload.java +++ b/launch/interface/src/main/java/xsbti/FullReload.java @@ -3,9 +3,17 @@ package xsbti; public final class FullReload extends RuntimeException { private final String[] arguments; + private final boolean clean; public FullReload(String[] arguments) { this.arguments = arguments; + this.clean = false; } + public FullReload(String[] arguments, boolean clean) + { + this.arguments = arguments; + this.clean = clean; + } + public boolean clean() { return clean; } public String[] arguments() { return arguments; } } \ No newline at end of file diff --git a/launch/interface/src/main/java/xsbti/Launcher.java b/launch/interface/src/main/java/xsbti/Launcher.java index cd5752a9c..b20b050d7 100644 --- a/launch/interface/src/main/java/xsbti/Launcher.java +++ b/launch/interface/src/main/java/xsbti/Launcher.java @@ -1,9 +1,14 @@ package xsbti; + import java.io.File; + public interface Launcher { public static final int InterfaceVersion = 1; public ScalaProvider getScala(String version); public ClassLoader topLoader(); public GlobalLock globalLock(); + public File bootDirectory(); + // null if none set + public File cacheDirectory(); } \ No newline at end of file diff --git a/launch/interface/src/main/java/xsbti/Manage.java b/launch/interface/src/main/java/xsbti/Manage.java new file mode 100644 index 000000000..fb5fcecd2 --- /dev/null +++ b/launch/interface/src/main/java/xsbti/Manage.java @@ -0,0 +1,6 @@ +package xsbti; + +enum Manage +{ + Nop, Clean, Refresh; +} \ No newline at end of file diff --git a/main/CommandSupport.scala b/main/CommandSupport.scala index c7d9c17c3..0b68e28b6 100644 --- a/main/CommandSupport.scala +++ b/main/CommandSupport.scala @@ -152,11 +152,15 @@ ProjectCommand + def DefaultsDetailed = "Registers default built-in commands" def RebootCommand = "reboot" - def RebootBrief = "Reboots sbt and then executes the remaining commands." + def RebootSummary = RebootCommand + " [full]" + def RebootBrief = (RebootSummary, "Reboots sbt and then executes the remaining commands.") def RebootDetailed = -RebootCommand + """ - This command is equivalent to exiting, restarting, and running the +RebootSummary + """ + This command is equivalent to exiting sbt, restarting, and running the remaining commands with the exception that the jvm is not shut down. + If 'full' is specified, the `project/boot` directory is deleted before + restarting. This forces an update of sbt and Scala and is useful when + working with development versions of sbt or Scala. """ def Multi = ";" diff --git a/main/Main.scala b/main/Main.scala index ae6ecb475..50e8eb229 100644 --- a/main/Main.scala +++ b/main/Main.scala @@ -51,6 +51,7 @@ class xMain extends xsbti.AppMain ErrorHandling.wideConvert { state.process(Command.process) } match { case Right(s) => s + case Left(t: xsbti.FullReload) => throw t case Left(t) => BuiltinCommands.handleException(t, state) } } @@ -140,9 +141,10 @@ object BuiltinCommands } def clearOnFailure = Command.command(ClearOnFailure)(s => s.copy(onFailure = None)) - def reboot = Command.command(RebootCommand, RebootBrief, RebootDetailed) { s => - s.runExitHooks().reload + def reboot = Command(RebootCommand, RebootBrief, RebootDetailed)(rebootParser) { (s, full) => + s.runExitHooks().reboot(full) } + def rebootParser(s: State) = token(Space ~> "full" ^^^ true) ?? false def defaults = Command.command(DefaultsCommand) { s => s ++ DefaultCommands diff --git a/main/State.scala b/main/State.scala index b8bbaf307..5d5ec1e19 100644 --- a/main/State.scala +++ b/main/State.scala @@ -31,6 +31,7 @@ trait StateOps { def ::: (commands: Seq[String]): State def :: (command: String): State def continue: State + def reboot(full: Boolean): State def reload: State def exit(ok: Boolean): State def fail: State @@ -57,6 +58,7 @@ object State def baseDir: File = s.configuration.baseDirectory def setNext(n: Next.Value) = s.copy(next = n) def continue = setNext(Next.Continue) + def reboot(full: Boolean) = throw new xsbti.FullReload(s.commands.toArray, full) def reload = setNext(Next.Reload) def exit(ok: Boolean) = setNext(if(ok) Next.Fail else Next.Done) def get[T](key: AttributeKey[T]) = s.attributes.get(key)