mirror of https://github.com/sbt/sbt.git
support reason for retrieving jars in launcher
specifically, identify when a Scala version is downloaded for running the application itself
This commit is contained in:
parent
715f7b8574
commit
988c22c653
|
|
@ -6,15 +6,15 @@ package xsbt.boot
|
|||
import java.lang.ref.{Reference, SoftReference}
|
||||
import java.util.HashMap
|
||||
|
||||
final class Cache[K,V](create: K => V) extends NotNull
|
||||
final class Cache[K,X,V](create: (K,X) => V)
|
||||
{
|
||||
private[this] val delegate = new HashMap[K,Reference[V]]
|
||||
def apply(k: K): V = getFromReference(k, delegate.get(k))
|
||||
private[this] def getFromReference(k: K, existingRef: Reference[V]) = if(existingRef eq null) newEntry(k) else get(k, existingRef.get)
|
||||
private[this] def get(k: K, existing: V) = if(existing == null) newEntry(k) else existing
|
||||
private[this] def newEntry(k: K): V =
|
||||
def apply(k: K, x: X): V = getFromReference(k, x, delegate.get(k))
|
||||
private[this] def getFromReference(k: K, x: X, existingRef: Reference[V]) = if(existingRef eq null) newEntry(k, x) else get(k, x, existingRef.get)
|
||||
private[this] def get(k: K, x: X, existing: V) = if(existing == null) newEntry(k, x) else existing
|
||||
private[this] def newEntry(k: K, x: X): V =
|
||||
{
|
||||
val v = create(k)
|
||||
val v = create(k, x)
|
||||
Pre.assert(v != null, "Value for key " + k + " was null")
|
||||
delegate.put(k, new SoftReference(v))
|
||||
v
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ object ConfigurationParser
|
|||
|
||||
implicit val readIDs = ids _
|
||||
}
|
||||
class ConfigurationParser extends NotNull
|
||||
class ConfigurationParser
|
||||
{
|
||||
def apply(file: File): LaunchConfiguration = Using(new InputStreamReader(new FileInputStream(file), "UTF-8"))(apply)
|
||||
def apply(s: String): LaunchConfiguration = Using(new StringReader(s))(apply)
|
||||
|
|
@ -191,7 +191,7 @@ class ConfigurationParser extends NotNull
|
|||
}
|
||||
}
|
||||
|
||||
sealed trait Line extends NotNull
|
||||
sealed trait Line
|
||||
final class Labeled(val label: String, val value: Option[String]) extends Line
|
||||
final class Section(val name: String) extends Line
|
||||
object Comment extends Line
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ package xsbt.boot
|
|||
import Pre._
|
||||
import scala.collection.immutable.List
|
||||
|
||||
class Enumeration extends NotNull
|
||||
class Enumeration
|
||||
{
|
||||
def elements: List[Value] = members
|
||||
private lazy val members: List[Value] =
|
||||
|
|
@ -25,6 +25,6 @@ class Enumeration extends NotNull
|
|||
}
|
||||
def value(s: String) = new Value(s, 0)
|
||||
def value(s: String, i: Int) = new Value(s, i)
|
||||
class Value(override val toString: String, val id: Int) extends NotNull
|
||||
final class Value(override val toString: String, val id: Int)
|
||||
def toValue(s: String): Value = elements.find(_.toString == s).getOrElse(error("Expected one of " + elements.mkString(",") + " (got: " + s + ")"))
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import java.net.URI
|
|||
import scala.collection.immutable.List
|
||||
|
||||
object Find { def apply(config: LaunchConfiguration, currentDirectory: File) = (new Find(config))(currentDirectory) }
|
||||
class Find(config: LaunchConfiguration) extends NotNull
|
||||
class Find(config: LaunchConfiguration)
|
||||
{
|
||||
import config.boot.search
|
||||
def apply(currentDirectory: File) =
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2008, 2009, 2010 Mark Harrah
|
||||
* Copyright 2008, 2009, 2010, 2011 Mark Harrah
|
||||
*/
|
||||
package xsbt.boot
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ object Launch
|
|||
def run(launcher: xsbti.Launcher)(config: RunConfiguration): xsbti.MainResult =
|
||||
{
|
||||
import config._
|
||||
val scalaProvider: xsbti.ScalaProvider = launcher.getScala(scalaVersion)
|
||||
val scalaProvider: xsbti.ScalaProvider = launcher.getScala(scalaVersion, "(for " + app.name + ")")
|
||||
val appProvider: xsbti.AppProvider = scalaProvider.app(app)
|
||||
val appConfig: xsbti.AppConfiguration = new AppConfiguration(toArray(arguments), workingDirectory, appProvider)
|
||||
|
||||
|
|
@ -73,15 +73,16 @@ object Launch
|
|||
}
|
||||
}
|
||||
}
|
||||
final class RunConfiguration(val scalaVersion: String, val app: xsbti.ApplicationID, val workingDirectory: File, val arguments: List[String]) extends NotNull
|
||||
final class RunConfiguration(val scalaVersion: String, val app: xsbti.ApplicationID, val workingDirectory: File, val arguments: List[String])
|
||||
|
||||
import BootConfiguration.{appDirectoryName, baseDirectoryName, ScalaDirectoryName, TestLoadScalaClasses}
|
||||
class Launch private[xsbt](val bootDirectory: File, val ivyOptions: IvyOptions) extends xsbti.Launcher
|
||||
{
|
||||
import ivyOptions.{classifiers, repositories}
|
||||
bootDirectory.mkdirs
|
||||
private val scalaProviders = new Cache[String, ScalaProvider](new ScalaProvider(_))
|
||||
def getScala(version: String): xsbti.ScalaProvider = scalaProviders(version)
|
||||
private val scalaProviders = new Cache[String, String, ScalaProvider](new ScalaProvider(_, _))
|
||||
def getScala(version: String): xsbti.ScalaProvider = getScala(version, "")
|
||||
def getScala(version: String, reason: String): xsbti.ScalaProvider = scalaProviders(version, reason)
|
||||
|
||||
lazy val topLoader = (new JNAProvider).loader
|
||||
val updateLockFile = new File(bootDirectory, "sbt.boot.lock")
|
||||
|
|
@ -103,7 +104,7 @@ class Launch private[xsbt](val bootDirectory: File, val ivyOptions: IvyOptions)
|
|||
def lockFile = updateLockFile
|
||||
}
|
||||
|
||||
class ScalaProvider(val version: String) extends xsbti.ScalaProvider with Provider
|
||||
class ScalaProvider(val version: String, override val reason: String) extends xsbti.ScalaProvider with Provider
|
||||
{
|
||||
def launcher: xsbti.Launcher = Launch.this
|
||||
def parentLoader = topLoader
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ final case class LaunchConfiguration(scalaVersion: Value[String], ivyConfigurati
|
|||
LaunchConfiguration(new Explicit(newScalaVersion), ivyConfiguration.copy(classifiers = classifiers0), app.withVersion(new Explicit(newAppVersion)), boot, logging, appProperties)
|
||||
def map(f: File => File) = LaunchConfiguration(scalaVersion, ivyConfiguration, app.map(f), boot.map(f), logging, appProperties)
|
||||
}
|
||||
final case class IvyOptions(ivyHome: Option[File], classifiers: Classifiers, repositories: List[Repository]) extends NotNull
|
||||
final case class IvyOptions(ivyHome: Option[File], classifiers: Classifiers, repositories: List[Repository])
|
||||
|
||||
sealed trait Value[T]
|
||||
final class Explicit[T](val value: T) extends Value[T] {
|
||||
|
|
@ -43,7 +43,7 @@ object Classifiers {
|
|||
def apply(forScala: List[String], app: List[String]):Classifiers = Classifiers(new Explicit(forScala), new Explicit(app))
|
||||
}
|
||||
|
||||
final case class Application(groupID: String, name: String, version: Value[String], main: String, components: List[String], crossVersioned: Boolean, classpathExtra: Array[File]) extends NotNull
|
||||
final case class Application(groupID: String, name: String, version: Value[String], main: String, components: List[String], crossVersioned: Boolean, classpathExtra: Array[File])
|
||||
{
|
||||
def getVersion = Value.get(version)
|
||||
def withVersion(newVersion: Value[String]) = Application(groupID, name, newVersion, main, components, crossVersioned, classpathExtra)
|
||||
|
|
@ -61,7 +61,7 @@ object Application
|
|||
}
|
||||
}
|
||||
|
||||
sealed trait Repository extends NotNull
|
||||
sealed trait Repository
|
||||
object Repository
|
||||
{
|
||||
final case class Maven(id: String, url: URL) extends Repository
|
||||
|
|
@ -82,7 +82,7 @@ object Repository
|
|||
def defaults: List[Repository] = Predefined.elements.map(Predefined.apply).toList
|
||||
}
|
||||
|
||||
final case class Search(tpe: Search.Value, paths: List[File]) extends NotNull
|
||||
final case class Search(tpe: Search.Value, paths: List[File])
|
||||
object Search extends Enumeration
|
||||
{
|
||||
def none = Search(Current, Nil)
|
||||
|
|
@ -93,17 +93,17 @@ object Search extends Enumeration
|
|||
def apply(s: String, paths: List[File]): Search = Search(toValue(s), paths)
|
||||
}
|
||||
|
||||
final case class BootSetup(directory: File, properties: File, search: Search, promptCreate: String, enableQuick: Boolean, promptFill: Boolean) extends NotNull
|
||||
final case class BootSetup(directory: File, properties: File, search: Search, promptCreate: String, enableQuick: Boolean, promptFill: Boolean)
|
||||
{
|
||||
def map(f: File => File) = BootSetup(f(directory), f(properties), search, promptCreate, enableQuick, promptFill)
|
||||
}
|
||||
final case class AppProperty(name: String)(val quick: Option[PropertyInit], val create: Option[PropertyInit], val fill: Option[PropertyInit]) extends NotNull
|
||||
final case class AppProperty(name: String)(val quick: Option[PropertyInit], val create: Option[PropertyInit], val fill: Option[PropertyInit])
|
||||
|
||||
sealed trait PropertyInit extends NotNull
|
||||
sealed trait PropertyInit
|
||||
final class SetProperty(val value: String) extends PropertyInit
|
||||
final class PromptProperty(val label: String, val default: Option[String]) extends PropertyInit
|
||||
|
||||
final class Logging(level: LogLevel.Value) extends NotNull
|
||||
final class Logging(level: LogLevel.Value)
|
||||
{
|
||||
def log(s: => String, at: LogLevel.Value) = if(level.id <= at.id) stream(at).println("[" + at + "] " + s)
|
||||
def debug(s: => String) = log(s, LogLevel.Debug)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import scala.collection.{Iterable, Iterator}
|
|||
import scala.collection.immutable.List
|
||||
|
||||
// preserves iteration order
|
||||
sealed class ListMap[K,V] private(backing: List[(K,V)]) extends Iterable[(K,V)] with NotNull // use Iterable because Traversable.toStream loops
|
||||
sealed class ListMap[K,V] private(backing: List[(K,V)]) extends Iterable[(K,V)] // use Iterable because Traversable.toStream loops
|
||||
{
|
||||
import ListMap.remove
|
||||
def update(k: K, v: V) = this.+( (k,v) )
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ object GetLocks
|
|||
// gets a file lock by first getting a JVM-wide lock.
|
||||
object Locks extends xsbti.GlobalLock
|
||||
{
|
||||
private[this] val locks = new Cache[File, GlobalLock](new GlobalLock(_))
|
||||
private[this] val locks = new Cache[File, Unit, GlobalLock]( (f, _) => new GlobalLock(f))
|
||||
def apply[T](file: File, action: Callable[T]): T =
|
||||
{
|
||||
val lock =
|
||||
|
|
@ -31,7 +31,7 @@ object Locks extends xsbti.GlobalLock
|
|||
{
|
||||
file.getParentFile.mkdirs()
|
||||
file.createNewFile()
|
||||
locks(file.getCanonicalFile)
|
||||
locks(file.getCanonicalFile, ())
|
||||
}
|
||||
lock.withLock(action)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2009, 2010 Mark Harrah
|
||||
* Copyright 2009, 2010, 2011 Mark Harrah
|
||||
*/
|
||||
package xsbt.boot
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ import java.io.{File, FileFilter}
|
|||
import java.net.{URL, URLClassLoader}
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
trait Provider extends NotNull
|
||||
trait Provider
|
||||
{
|
||||
def configuration: UpdateConfiguration
|
||||
def baseDirectories: List[File]
|
||||
|
|
@ -21,7 +21,8 @@ trait Provider extends NotNull
|
|||
|
||||
def classpath: Array[File] = Provider.getJars(baseDirectories)
|
||||
def fullClasspath:Array[File] = concat(classpath, extraClasspath)
|
||||
|
||||
|
||||
def reason: String = ""
|
||||
def retrieveFailed: Nothing = fail("")
|
||||
def retrieveCorrupt(missing: Iterable[String]): Nothing = fail(": missing " + missing.mkString(", "))
|
||||
private def fail(extra: String) =
|
||||
|
|
@ -38,7 +39,7 @@ trait Provider extends NotNull
|
|||
(existingJars, existingLoader)
|
||||
else
|
||||
{
|
||||
val retrieveSuccess = ( new Update(configuration) )(target)
|
||||
val retrieveSuccess = ( new Update(configuration) )(target, reason)
|
||||
if(retrieveSuccess)
|
||||
{
|
||||
val (newJars, newLoader) = createLoader
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ object ResolveValues
|
|||
}
|
||||
|
||||
import ResolveValues.{readProperties, trim}
|
||||
final class ResolveValues(conf: LaunchConfiguration) extends NotNull
|
||||
final class ResolveValues(conf: LaunchConfiguration)
|
||||
{
|
||||
private def propertiesFile = conf.boot.properties
|
||||
private lazy val properties = readProperties(propertiesFile)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
package xsbt.boot
|
||||
|
||||
import jline.ConsoleReader
|
||||
abstract class JLine extends NotNull
|
||||
abstract class JLine
|
||||
{
|
||||
protected[this] val reader: ConsoleReader
|
||||
def readLine(prompt: String) = JLine.withJLine { unsynchronizedReadLine(prompt) }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2009, 2010 Mark Harrah
|
||||
* Copyright 2009, 2010, 2011 Mark Harrah
|
||||
*/
|
||||
package xsbt.boot
|
||||
|
||||
|
|
@ -62,16 +62,16 @@ final class Update(config: UpdateConfiguration)
|
|||
private lazy val ivyLockFile = new File(settings.getDefaultIvyUserDir, ".sbt.ivy.lock")
|
||||
|
||||
/** The main entry point of this class for use by the Update module. It runs Ivy */
|
||||
def apply(target: UpdateTarget): Boolean =
|
||||
def apply(target: UpdateTarget, reason: String): Boolean =
|
||||
{
|
||||
Message.setDefaultLogger(new SbtIvyLogger(logWriter))
|
||||
val action = new Callable[Boolean] { def call = lockedApply(target) }
|
||||
val action = new Callable[Boolean] { def call = lockedApply(target, reason) }
|
||||
Locks(ivyLockFile, action)
|
||||
}
|
||||
private def lockedApply(target: UpdateTarget) =
|
||||
private def lockedApply(target: UpdateTarget, reason: String) =
|
||||
{
|
||||
ivy.pushContext()
|
||||
try { update(target); true }
|
||||
try { update(target, reason); true }
|
||||
catch
|
||||
{
|
||||
case e: Exception =>
|
||||
|
|
@ -87,7 +87,7 @@ final class Update(config: UpdateConfiguration)
|
|||
}
|
||||
}
|
||||
/** Runs update for the specified target (updates either the scala or appliciation jars for building the project) */
|
||||
private def update(target: UpdateTarget)
|
||||
private def update(target: UpdateTarget, reason: String)
|
||||
{
|
||||
import IvyConfiguration.Visibility.PUBLIC
|
||||
// the actual module id here is not that important
|
||||
|
|
@ -100,13 +100,13 @@ final class Update(config: UpdateConfiguration)
|
|||
case u: UpdateScala =>
|
||||
addDependency(moduleID, ScalaOrg, CompilerModuleName, scalaVersion, "default;optional", u.classifiers)
|
||||
addDependency(moduleID, ScalaOrg, LibraryModuleName, scalaVersion, "default", u.classifiers)
|
||||
System.out.println("Getting Scala " + scalaVersion + " ...")
|
||||
System.out.println("Getting Scala " + scalaVersion + " " + reason + "...")
|
||||
case u: UpdateApp =>
|
||||
val app = u.id
|
||||
val resolvedName = if(app.crossVersioned) app.name + "_" + scalaVersion else app.name
|
||||
addDependency(moduleID, app.groupID, resolvedName, app.getVersion, "default(compile)", u.classifiers)
|
||||
excludeScala(moduleID)
|
||||
System.out.println("Getting " + app.groupID + " " + resolvedName + " " + app.getVersion + " ...")
|
||||
System.out.println("Getting " + app.groupID + " " + resolvedName + " " + app.getVersion + " " + reason + "...")
|
||||
}
|
||||
update(moduleID, target)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ package xsbt.boot
|
|||
|
||||
import java.io.{Closeable, File, FileInputStream, FileOutputStream, InputStream, OutputStream}
|
||||
|
||||
object Using extends NotNull
|
||||
object Using
|
||||
{
|
||||
def apply[R <: Closeable,T](create: R)(f: R => T): T = withResource(create)(f)
|
||||
def withResource[R <: Closeable,T](r: R)(f: R => T): T = try { f(r) } finally { r.close() }
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ public interface Launcher
|
|||
{
|
||||
public static final int InterfaceVersion = 1;
|
||||
public ScalaProvider getScala(String version);
|
||||
public ScalaProvider getScala(String version, String reason);
|
||||
public ClassLoader topLoader();
|
||||
public GlobalLock globalLock();
|
||||
public File bootDirectory();
|
||||
|
|
|
|||
Loading…
Reference in New Issue