mirror of https://github.com/sbt/sbt.git
Merge pull request #1037 from jsuereth/wip/launcher-improvements
Minor launcher improvements
This commit is contained in:
commit
8f22d7d580
|
|
@ -2,6 +2,11 @@ package xsbti;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* This represents an interface that can generate applications.
|
||||
*
|
||||
* An application is somethign which will run and return an exit value.
|
||||
*/
|
||||
public interface AppProvider
|
||||
{
|
||||
/** Returns the ScalaProvider that this AppProvider will use. */
|
||||
|
|
@ -34,5 +39,8 @@ public interface AppProvider
|
|||
/** The classpath from which the main class is loaded, excluding Scala jars.*/
|
||||
public File[] mainClasspath();
|
||||
|
||||
/** Returns a mechanism you can use to install/find/resolve components.
|
||||
* A component is just a related group of files.
|
||||
*/
|
||||
public ComponentProvider components();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,52 @@ package xsbti;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
/**
|
||||
* A service to locate, install and modify "Components".
|
||||
*
|
||||
* A component is essentially a directory and a set of files attached to a unique string id.
|
||||
*/
|
||||
public interface ComponentProvider
|
||||
{
|
||||
/**
|
||||
* @param id The component's id string.
|
||||
* @return
|
||||
* The "working directory" or base directory for the component. You should perform temporary work here for the component.
|
||||
*/
|
||||
public File componentLocation(String id);
|
||||
/**
|
||||
* Grab the current component definition.
|
||||
*
|
||||
* @param componentID The component's id string.
|
||||
* @return
|
||||
* The set of files attached to this component.
|
||||
*/
|
||||
public File[] component(String componentID);
|
||||
/**
|
||||
* This will define a new component using the files passed in.
|
||||
*
|
||||
* Note: The component will copy/move the files into a cache location. You should not use them directly, but
|
||||
* look them up using the `component` method.
|
||||
*
|
||||
* @param componentID The component's id string
|
||||
* @param components The set of files which defines the component.
|
||||
*
|
||||
* @throws BootException if the component is already defined.
|
||||
*/
|
||||
public void defineComponent(String componentID, File[] components);
|
||||
/**
|
||||
* Modify an existing component by adding files to it.
|
||||
*
|
||||
* @param componentID The component's id string
|
||||
* @param components The set of new files to add to the component.
|
||||
* @return true if any files were copied and false otherwise.
|
||||
*
|
||||
*/
|
||||
public boolean addToComponent(String componentID, File[] components);
|
||||
// null if locking disabled
|
||||
/**
|
||||
* @return The lockfile you should use to ensure your component cache does not become corrupted.
|
||||
* May return null if there is no lockfile for this provider.
|
||||
*/
|
||||
public File lockFile();
|
||||
}
|
||||
|
|
@ -15,42 +15,50 @@ object Launch
|
|||
{
|
||||
def apply(arguments: List[String]): Option[Int] = apply( (new File("")).getAbsoluteFile , arguments )
|
||||
|
||||
def apply(currentDirectory: File, arguments: List[String]): Option[Int] =
|
||||
Configuration.find(arguments, currentDirectory) match { case (configLocation, newArguments) => configured(currentDirectory, configLocation, newArguments) }
|
||||
|
||||
def configured(currentDirectory: File, configLocation: URL, arguments: List[String]): Option[Int] =
|
||||
{
|
||||
val config = Configuration.parse(configLocation, currentDirectory)
|
||||
Find(config, currentDirectory) match { case (resolved, baseDirectory) => parsed(baseDirectory, resolved, arguments) }
|
||||
def apply(currentDirectory: File, arguments: List[String]): Option[Int] = {
|
||||
val (configLocation, newArguments) = Configuration.find(arguments, currentDirectory)
|
||||
val config = parseAndInitializeConfig(configLocation, currentDirectory)
|
||||
launch(run(Launcher(config)))(makeRunConfig(currentDirectory, config, newArguments))
|
||||
}
|
||||
def parsed(currentDirectory: File, parsed: LaunchConfiguration, arguments: List[String]): Option[Int] =
|
||||
/** Parses the configuration *and* runs the initialization code that will remove variable references. */
|
||||
def parseAndInitializeConfig(configLocation: URL, currentDirectory: File): LaunchConfiguration =
|
||||
{
|
||||
val (parsed, bd) = parseConfiguration(configLocation, currentDirectory)
|
||||
resolveConfig(parsed)
|
||||
}
|
||||
/** Parse configuration and return it and the baseDirectory of the launch. */
|
||||
def parseConfiguration(configLocation: URL, currentDirectory: File): (LaunchConfiguration, File) =
|
||||
Find(Configuration.parse(configLocation, currentDirectory), currentDirectory)
|
||||
|
||||
/** Setups the Initialize object so we can fill in system properties in the configuration */
|
||||
def resolveConfig(parsed: LaunchConfiguration): LaunchConfiguration =
|
||||
{
|
||||
// Set up initialize.
|
||||
val propertiesFile = parsed.boot.properties
|
||||
import parsed.boot.{enableQuick, promptCreate, promptFill}
|
||||
if(isNonEmpty(promptCreate) && !propertiesFile.exists)
|
||||
Initialize.create(propertiesFile, promptCreate, enableQuick, parsed.appProperties)
|
||||
else if(promptFill)
|
||||
Initialize.fill(propertiesFile, parsed.appProperties)
|
||||
initialized(currentDirectory, parsed, arguments)
|
||||
}
|
||||
def initialized(currentDirectory: File, parsed: LaunchConfiguration, arguments: List[String]): Option[Int] =
|
||||
{
|
||||
|
||||
parsed.logging.debug("Parsed configuration: " + parsed)
|
||||
val resolved = ResolveValues(parsed)
|
||||
resolved.logging.debug("Resolved configuration: " + resolved)
|
||||
explicit(currentDirectory, resolved, arguments)
|
||||
resolved
|
||||
}
|
||||
|
||||
def explicit(currentDirectory: File, explicit: LaunchConfiguration, arguments: List[String]): Option[Int] =
|
||||
launch( run(Launcher(explicit)) ) (
|
||||
new RunConfiguration(explicit.getScalaVersion, explicit.app.toID, currentDirectory, arguments) )
|
||||
/** Create run configuration we'll use to launch the app. */
|
||||
def makeRunConfig(currentDirectory: File, config: LaunchConfiguration, arguments: List[String]): RunConfiguration =
|
||||
new RunConfiguration(config.getScalaVersion, config.app.toID, currentDirectory, arguments)
|
||||
|
||||
/** The actual mechanism used to run a launched application. */
|
||||
def run(launcher: xsbti.Launcher)(config: RunConfiguration): xsbti.MainResult =
|
||||
{
|
||||
import config._
|
||||
val appProvider: xsbti.AppProvider = launcher.app(app, orNull(scalaVersion)) // takes ~40 ms when no update is required
|
||||
val appConfig: xsbti.AppConfiguration = new AppConfiguration(toArray(arguments), workingDirectory, appProvider)
|
||||
|
||||
// TODO - Jansi probably should be configurable via some other mechanism...
|
||||
JAnsi.install(launcher.topLoader)
|
||||
try {
|
||||
val main = appProvider.newMain()
|
||||
|
|
|
|||
Loading…
Reference in New Issue