Permalink
Browse files

Turned sbt launcher into a general Scala application launcher as desc…

…ribed in launch.specification
  • Loading branch information...
1 parent 56e96c3 commit b2fdc0750585e243c8852a6f3b8ed1d139285996 @harrah committed Sep 27, 2009
@@ -35,9 +35,9 @@ class AnalyzingCompiler(scalaInstance: ScalaInstance, manager: ComponentManager)
new DualLoader(scalaLoader, notXsbtiFilter, x => true, sbtLoader, xsbtiFilter, x => false)
}
override def toString = "Analyzing compiler (Scala " + scalaInstance.actualVersion + ")"
-}
+}/*
object AnalyzingCompiler
{
def apply(scalaVersion: String, provider: xsbti.ScalaProvider, manager: ComponentManager): AnalyzingCompiler =
new AnalyzingCompiler(ScalaInstance(scalaVersion, provider), manager)
-}
+}*/
@@ -27,12 +27,13 @@ class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager)
protected def compileAndInstall(id: String, binID: String): File =
{
val srcID = id + srcExtension
- val binaryDirectory = manager.location(binID)
- createDirectory(binaryDirectory)
- val targetJar = new File(binaryDirectory, id + ".jar")
- compileSources(manager.files(srcID), targetJar, id)
- manager.cache(binID)
- targetJar
+ withTemporaryDirectory { binaryDirectory =>
+ val targetJar = new File(binaryDirectory, id + ".jar")
+ compileSources(manager.files(srcID), targetJar, id)
+ manager.define(binID, Seq(targetJar))
+ manager.cache(binID)
+ }
+ manager.file(binID)
}
/** Extract sources from source jars, compile them with the xsbti interfaces on the classpath, and package the compiled classes and
* any resources from the source jars into a final jar.*/
@@ -21,12 +21,8 @@ object ScalaInstance
{
val VersionPrefix = "version "
/** Creates a ScalaInstance using the given provider to obtain the jars and loader.*/
- def apply(version: String, provider: xsbti.ScalaProvider) =
- {
- val scalaLibDirectory = provider.getScalaHome(version)
- // these get the locations of the scala jars given the location of the lib/ directory
- val libraryJar = new File(scalaLibDirectory, "scala-library.jar")
- val compilerJar = new File(scalaLibDirectory, "scala-compiler.jar")
- new ScalaInstance(version, provider.getScalaLoader(version), libraryJar, compilerJar)
- }
+ def apply(version: String, launcher: xsbti.Launcher): ScalaInstance =
+ apply(version, launcher.getScala(version))
+ def apply(version: String, provider: xsbti.ScalaProvider): ScalaInstance =
+ new ScalaInstance(version, provider.loader, provider.libraryJar, provider.compilerJar)
}
@@ -34,34 +34,23 @@ object WithCompiler
val log = new TestIvyLogger with CompileLogger
log.setLevel(Level.Debug)
log.bufferQuietly {
- FileUtilities.withTemporaryDirectory { temp =>
- val launch = new xsbt.boot.Launch(temp)
- val sbtVersion = xsbti.Versions.Sbt
- val manager = new ComponentManager(launch.getSbtHome(sbtVersion, scalaVersion), log)
- prepare(manager, ComponentCompiler.compilerInterfaceSrcID, "CompilerInterface.scala")
- prepare(manager, ComponentCompiler.xsbtiID, classOf[xsbti.AnalysisCallback])
- val result = f(AnalyzingCompiler(scalaVersion, launch, manager), log)
- launch.clearScalaLoaderCache
- System.gc()
- System.gc()
- System.gc()
- result
+ boot.LaunchTest.withLauncher { launch =>
+ FileUtilities.withTemporaryDirectory { componentDirectory =>
+ val manager = new ComponentManager(new boot.ComponentProvider(componentDirectory), log)
+ prepare(manager, ComponentCompiler.compilerInterfaceSrcID, "CompilerInterface.scala")
+ prepare(manager, ComponentCompiler.xsbtiID, classOf[xsbti.AnalysisCallback])
+ f(new AnalyzingCompiler(ScalaInstance(scalaVersion, launch), manager), log)
+ }
}
}
}
private def prepare(manager: ComponentManager, id: String, resource: Class[_]): Unit =
- {
- val src = FileUtilities.classLocationFile(resource)
- prepare(manager, id, src)
- }
+ manager.define(id, FileUtilities.classLocationFile(resource) :: Nil)
private def prepare(manager: ComponentManager, id: String, resource: String): Unit =
{
val src = getClass.getClassLoader.getResource(resource)
if(src eq null)
error("Resource not found: " + resource)
- prepare(manager, id, FileUtilities.asFile(src))
+ manager.define(id, FileUtilities.asFile(src) :: Nil)
}
- import Paths._
- private def prepare(manager: ComponentManager, id: String, file: File): Unit =
- FileUtilities.copy(file x FileMapper.flat(manager.location(id)))
}
@@ -5,7 +5,7 @@
public interface Versions
{
- public static final String Sbt = "0.7";
+ public static final String Sbt = "0.7.0_13"; // keep in sync with LauncherProject in the XSbt project definition;
public static final int Interface = 1;
public static final int BootInterface = 1;
}
View
@@ -1,7 +1,6 @@
package xsbt
import java.io.File
-import xsbti.Versions
/** A component manager provides access to the pieces of xsbt that are distributed as components.
* There are two types of components. The first type is compiled subproject jars with their dependencies.
@@ -12,30 +11,13 @@ import xsbti.Versions
* This is used for compiled source jars so that the compilation need not be repeated for other projects on the same
* machine.
*/
-class ComponentManager(baseDirectory: File, log: IvyLogger) extends NotNull
+class ComponentManager(provider: xsbti.ComponentProvider, log: IvyLogger) extends NotNull
{
- /** Get the location where files for component 'id' are stored. This method does not ensure that the component is retrieved from the
- * local repository. By default, the location returned is is baseDirectory / id.*/
- def location(id: String): File = new File(baseDirectory, id)
- /** Get the location where files for component 'id' are stored. If the component has not yet been retrieved from the local repository,
- * it is retrieved first. */
- def directory(id: String): File =
- {
- val dir = location(id)
- if(!dir.exists)
- update(id)
- dir
- }
- // get the contents of the given directory, wrapping a null result in an empty list.
- private def contents(dir: File): Seq[File] =
- {
- val fs = dir.listFiles
- if(fs == null) Nil else fs
- }
/** Get all of the files for component 'id', throwing an exception if no files exist for the component. */
def files(id: String): Iterable[File] =
{
- val fs = contents(directory(id))
+ val existing = provider.component(id)
+ val fs = if(existing.isEmpty) { update(id); provider.component(id) } else existing
if(!fs.isEmpty) fs else invalid("Could not find required component '" + id + "'")
}
/** Get the file for component 'id', throwing an exception if no files or multiple files exist for the component. */
@@ -47,12 +29,13 @@ class ComponentManager(baseDirectory: File, log: IvyLogger) extends NotNull
private def invalid(msg: String) = throw new InvalidComponent(msg)
private def invalid(e: NotInCache) = throw new InvalidComponent(e.getMessage, e)
+ def define(id: String, files: Iterable[File]) = provider.defineComponent(id, files.toSeq.toArray)
/** Retrieve the file for component 'id' from the local repository. */
def update(id: String): Unit =
- try { IvyCache.retrieveCachedJar(sbtModuleID(id), location(id), log) }
+ try { IvyCache.withCachedJar(sbtModuleID(id), log)(jar => define(id, Seq(jar)) ) }
catch { case e: NotInCache => invalid(e) }
- def sbtModuleID(id: String) = ModuleID("org.scala-tools.sbt", id, Versions.Sbt)
+ def sbtModuleID(id: String) = ModuleID("org.scala-tools.sbt", id, xsbti.Versions.Sbt)
/** Install the files for component 'id' to the local repository. This is usually used after writing files to the directory returned by 'location'. */
def cache(id: String): Unit = IvyCache.cacheJar(sbtModuleID(id), file(id), log)
def clearCache(id: String): Unit = IvyCache.clearCachedJar(sbtModuleID(id), log)
@@ -91,7 +91,7 @@ private object ConvertResolver
setKeyFilePassword(password)
}
}
- private def initializePatterns(resolver: AbstractPatternsBasedResolver, patterns: RepositoryHelpers.Patterns)
+ private def initializePatterns(resolver: AbstractPatternsBasedResolver, patterns: Patterns)
{
resolver.setM2compatible(patterns.isMavenCompatible)
patterns.ivyPatterns.foreach(resolver.addIvyPattern)
@@ -17,8 +17,10 @@ import plugins.repository.url.URLResource
private[xsbt] object CustomXmlParser extends XmlModuleDescriptorParser with NotNull
{
import XmlModuleDescriptorParser.Parser
- class CustomParser(settings: IvySettings) extends Parser(CustomXmlParser, settings) with NotNull
+ class CustomParser(settings: IvySettings, defaultConfig: Option[String]) extends Parser(CustomXmlParser, settings) with NotNull
{
+ defaultConfig.foreach(x => setDefaultConfMapping("*->default(compile)"))
+
def setSource(url: URL) =
{
super.setResource(new URLResource(url))
@@ -29,7 +31,6 @@ private[xsbt] object CustomXmlParser extends XmlModuleDescriptorParser with NotN
override def setResource(res: Resource) {}
override def setMd(md: DefaultModuleDescriptor) = super.setMd(md)
override def parseDepsConfs(confs: String, dd: DefaultDependencyDescriptor) = super.parseDepsConfs(confs, dd)
- override def getDefaultConf = super.getDefaultConf
- override def setDefaultConf(conf: String) = super.setDefaultConf(conf)
+ override def getDefaultConf = defaultConfig.getOrElse(super.getDefaultConf)
}
}
View
@@ -8,6 +8,7 @@ import Artifact.{defaultExtension, defaultType}
import java.io.File
import org.apache.ivy.{core, plugins, util, Ivy}
+import core.IvyPatternHelper
import core.cache.DefaultRepositoryCacheManager
import core.module.descriptor.{DefaultArtifact, DefaultDependencyArtifactDescriptor, MDArtifact}
import core.module.descriptor.{DefaultDependencyDescriptor, DefaultModuleDescriptor, ModuleDescriptor}
@@ -74,7 +75,7 @@ final class IvySbt(configuration: IvyConfiguration)
finally { ivy.popContext() }
}
- final class Module(val moduleConfiguration: ModuleConfiguration) extends NotNull
+ final class Module(val moduleSettings: ModuleSettings) extends NotNull
{
def logger = configuration.log
def withModule[T](f: (Ivy,DefaultModuleDescriptor,String) => T): T =
@@ -83,14 +84,14 @@ final class IvySbt(configuration: IvyConfiguration)
private lazy val (moduleDescriptor: DefaultModuleDescriptor, defaultConfig: String) =
{
val (baseModule, baseConfiguration) =
- moduleConfiguration match
+ moduleSettings match
{
case ic: InlineConfiguration => configureInline(ic)
case ec: EmptyConfiguration => configureEmpty(ec.module)
case pc: PomConfiguration => readPom(pc.file, pc.validate)
case ifc: IvyFileConfiguration => readIvyFile(ifc.file, ifc.validate)
}
- moduleConfiguration.ivyScala.foreach(IvyScala.checkModule(baseModule, baseConfiguration))
+ moduleSettings.ivyScala.foreach(IvyScala.checkModule(baseModule, baseConfiguration))
baseModule.getExtraAttributesNamespaces.asInstanceOf[java.util.Map[String,String]].put("e", "http://ant.apache.org/ivy/extra")
(baseModule, baseConfiguration)
}
@@ -105,6 +106,7 @@ final class IvySbt(configuration: IvyConfiguration)
IvySbt.addArtifacts(moduleID, artifacts)
IvySbt.addDependencies(moduleID, dependencies, parser)
+ IvySbt.setModuleConfigurations(settings, moduleConfigurations)
IvySbt.addMainArtifact(moduleID)
(moduleID, parser.getDefaultConf)
}
@@ -126,7 +128,7 @@ final class IvySbt(configuration: IvyConfiguration)
private def readIvyFile(ivyFile: File, validate: Boolean) =
{
val url = toURL(ivyFile)
- val parser = new CustomXmlParser.CustomParser(settings)
+ val parser = new CustomXmlParser.CustomParser(settings, None)
parser.setValidate(validate)
parser.setSource(url)
parser.parse()
@@ -168,6 +170,20 @@ private object IvySbt
settings.setDefaultResolver(newDefault.getName)
log.debug("Using repositories:\n" + resolvers.mkString("\n\t"))
}
+ private def setModuleConfigurations(settings: IvySettings, moduleConfigurations: Seq[ModuleConfiguration])
+ {
+ val existing = settings.getResolverNames
+ for(moduleConf <- moduleConfigurations)
+ {
+ import moduleConf._
+ import IvyPatternHelper._
+ import PatternMatcher._
+ if(!existing.contains(resolver.name))
+ settings.addResolver(ConvertResolver(resolver))
+ val attributes = javaMap(Map(MODULE_KEY -> name, ORGANISATION_KEY -> organization, REVISION_KEY -> revision))
+ settings.addModuleConfiguration(attributes, settings.getMatcher(EXACT_OR_REGEXP), resolver.name, null, null, null)
+ }
+ }
private def configureCache(settings: IvySettings, dir: Option[File])
{
val cacheDir = dir.getOrElse(settings.getDefaultRepositoryCacheBasedir())
@@ -244,9 +260,8 @@ private object IvySbt
/** Parses the given in-memory Ivy file 'xml', using the existing 'moduleID' and specifying the given 'defaultConfiguration'. */
private def parseIvyXML(settings: IvySettings, xml: String, moduleID: DefaultModuleDescriptor, defaultConfiguration: String, validate: Boolean): CustomXmlParser.CustomParser =
{
- val parser = new CustomXmlParser.CustomParser(settings)
+ val parser = new CustomXmlParser.CustomParser(settings, Some(defaultConfiguration))
parser.setMd(moduleID)
- parser.setDefaultConf(defaultConfiguration)
parser.setValidate(validate)
parser.setInput(xml.getBytes)
parser.parse()
View
@@ -27,7 +27,7 @@ object IvyActions
{
module.logger.info("Installing " + dependency)
val options = new InstallOptions
- options.setValidate(module.moduleConfiguration.validate)
+ options.setValidate(module.moduleSettings.validate)
options.setTransitive(dependency.isTransitive)
ivy.install(dependency.getDependencyRevisionId, from, to, options)
}
@@ -50,10 +50,8 @@ object IvyActions
// todo: correct default configuration for extra dependencies
private def addLateDependencies(ivy: Ivy, module: DefaultModuleDescriptor, defaultConfiguration: String, extraDependencies: Iterable[ModuleID])
{
- val parser = new CustomXmlParser.CustomParser(ivy.getSettings)
+ val parser = new CustomXmlParser.CustomParser(ivy.getSettings, Some(defaultConfiguration))
parser.setMd(module)
- val defaultConf = if(defaultConfiguration.contains("->")) defaultConfiguration else (defaultConfiguration + "->default(compile)")
- parser.setDefaultConf(defaultConf)
IvySbt.addDependencies(module, extraDependencies, parser)
}
private def getConfigurations(module: ModuleDescriptor, configurations: Option[Iterable[Configuration]]) =
View
@@ -40,19 +40,20 @@ object IvyCache
/** Clears the cache of the jar for the given ID.*/
def clearCachedJar(id: ModuleID, log: IvyLogger)
{
- try { getCachedFile(id, log).delete }
+ try { withCachedJar(id, log)(_.delete) }
catch { case e: Exception => log.debug("Error cleaning cached jar: " + e.toString) }
}
/** Copies the cached jar for the given ID to the directory 'toDirectory'. If the jar is not in the cache, NotInCache is thrown.*/
def retrieveCachedJar(id: ModuleID, toDirectory: File, log: IvyLogger) =
- {
- val cachedFile = getCachedFile(id, log)
- val copyTo = new File(toDirectory, cachedFile.getName)
- FileUtil.copy(cachedFile, copyTo, null)
- copyTo
- }
- /** Get the location of the cached jar for the given ID in the Ivy cache. If the jar is not in the cache, NotInCache is thrown.*/
- def getCachedFile(id: ModuleID, log: IvyLogger): File =
+ withCachedJar(id, log) { cachedFile =>
+ val copyTo = new File(toDirectory, cachedFile.getName)
+ FileUtil.copy(cachedFile, copyTo, null)
+ copyTo
+ }
+
+ /** Get the location of the cached jar for the given ID in the Ivy cache. If the jar is not in the cache, NotInCache is thrown
+ * TODO: locking.*/
+ def withCachedJar[T](id: ModuleID, log: IvyLogger)(f: File => T): T =
{
val cachedFile =
try
@@ -64,7 +65,7 @@ object IvyCache
}
catch { case e: Exception => throw new NotInCache(id, e) }
- if(cachedFile.exists) cachedFile else throw new NotInCache(id)
+ if(cachedFile.exists) f(cachedFile) else throw new NotInCache(id)
}
/** Calls the given function with the default Ivy cache.*/
def withDefaultCache[T](log: IvyLogger)(f: DefaultRepositoryCacheManager => T): T =
@@ -82,7 +83,7 @@ object IvyCache
{
val local = Resolver.defaultLocal
val paths = new IvyPaths(new File("."), None)
- val conf = new IvyConfiguration(paths, Seq(local), log)
+ val conf = new IvyConfiguration(paths, Seq(local), Nil, log)
(new IvySbt(conf), local)
}
/** Creates a default jar artifact based on the given ID.*/
@@ -7,19 +7,20 @@ import java.io.File
import scala.xml.NodeSeq
final class IvyPaths(val baseDirectory: File, val cacheDirectory: Option[File]) extends NotNull
-final class IvyConfiguration(val paths: IvyPaths, val resolvers: Seq[Resolver], val log: IvyLogger) extends NotNull
+final class IvyConfiguration(val paths: IvyPaths, val resolvers: Seq[Resolver],
+ val moduleConfigurations: Seq[ModuleConfiguration], val log: IvyLogger) extends NotNull
-sealed trait ModuleConfiguration extends NotNull
+sealed trait ModuleSettings extends NotNull
{
def validate: Boolean
def ivyScala: Option[IvyScala]
}
-final class IvyFileConfiguration(val file: File, val ivyScala: Option[IvyScala], val validate: Boolean) extends ModuleConfiguration
-final class PomConfiguration(val file: File, val ivyScala: Option[IvyScala], val validate: Boolean) extends ModuleConfiguration
+final class IvyFileConfiguration(val file: File, val ivyScala: Option[IvyScala], val validate: Boolean) extends ModuleSettings
+final class PomConfiguration(val file: File, val ivyScala: Option[IvyScala], val validate: Boolean) extends ModuleSettings
final class InlineConfiguration(val module: ModuleID, val dependencies: Iterable[ModuleID], val ivyXML: NodeSeq,
val configurations: Iterable[Configuration], val defaultConfiguration: Option[Configuration], val ivyScala: Option[IvyScala],
- val artifacts: Iterable[Artifact], val validate: Boolean) extends ModuleConfiguration
-final class EmptyConfiguration(val module: ModuleID, val ivyScala: Option[IvyScala], val validate: Boolean) extends ModuleConfiguration
+ val artifacts: Iterable[Artifact], val validate: Boolean) extends ModuleSettings
+final class EmptyConfiguration(val module: ModuleID, val ivyScala: Option[IvyScala], val validate: Boolean) extends ModuleSettings
object InlineConfiguration
{
def apply(module: ModuleID, dependencies: Iterable[ModuleID], artifacts: Iterable[Artifact]) =
@@ -37,7 +38,7 @@ object InlineConfiguration
else
explicitConfigurations
}
-object ModuleConfiguration
+object ModuleSettings
{
def apply(ivyScala: Option[IvyScala], validate: Boolean, module: => ModuleID)(baseDirectory: File, log: IvyLogger) =
{
Oops, something went wrong.

0 comments on commit b2fdc07

Please sign in to comment.