Cut down launcher jar size a bit

This commit is contained in:
Mark Harrah 2010-02-04 18:56:07 -05:00
parent a2758afd43
commit 8daaf9ea17
8 changed files with 72 additions and 11 deletions

View File

@ -35,6 +35,7 @@ object Configuration
if(exists) Some(resolved.toURL) else None
}
val against = resolveAgainst(baseDirectory)
// use Iterators so that resolution occurs lazily, for performance
val resolving = against.elements.flatMap(e => resolve(e).toList.elements)
if(!resolving.hasNext) multiPartError("Could not find configuration file '" + path + "'. Searched:", against)
resolving.next()

View File

@ -1,5 +1,6 @@
package xsbt.boot
import Pre._
import java.lang.Character.isWhitespace
import java.io.{BufferedReader, File, FileInputStream, InputStreamReader, Reader, StringReader}
@ -102,7 +103,7 @@ class ConfigurationParser extends NotNull
val (crossVersioned, m6) = id(m5, "cross-versioned", "true")
val (resources, m7) = ids(m6, "resources", Nil)
check(m7, "label")
val classpathExtra = toFiles(resources).toArray[File]
val classpathExtra = toArray(toFiles(resources))
new Application(org, name, rev, main, components, toBoolean(crossVersioned), classpathExtra)
}
def getRepositories(m: LabelMap): List[Repository] =

View File

@ -92,13 +92,13 @@ class Launch(val bootDirectory: File, repositories: List[Repository], scalaClass
lazy val scalaHome = new File(libDirectory, ScalaDirectoryName)
def compilerJar = new File(scalaHome,CompilerModuleName + ".jar")
def libraryJar = new File(scalaHome, LibraryModuleName + ".jar")
override def classpath = Array(compilerJar, libraryJar)
override def classpath = array(compilerJar, libraryJar)
def baseDirectories = List(scalaHome)
def testLoadClasses = TestLoadScalaClasses
def target = new UpdateScala(scalaClassifiers)
def failLabel = "Scala " + version
def lockFile = updateLockFile
def extraClasspath = Array[File]()
def extraClasspath = array()
def app(id: xsbti.ApplicationID): xsbti.AppProvider = new AppProvider(id)
@ -113,7 +113,7 @@ class Launch(val bootDirectory: File, repositories: List[Repository], scalaClass
def target = new UpdateApp(Application(id))
def failLabel = id.name + " " + id.version
def lockFile = updateLockFile
def mainClasspath = classpath ++ extraClasspath
def mainClasspath = fullClasspath
def extraClasspath = id.classpathExtra
lazy val mainClass: Class[T] forSome { type T <: xsbti.AppMain } =

View File

@ -28,4 +28,14 @@ object Pre
copy(0, list)
arr
}
/* These exist in order to avoid bringing in dependencies on RichInt and ArrayBuffer, among others. */
import java.io.File
def concat(a: Array[File], b: Array[File]): Array[File] =
{
val n = new Array[File](a.length + b.length)
java.lang.System.arraycopy(a, 0, n, 0, a.length)
java.lang.System.arraycopy(b, 0, n, a.length, b.length)
n
}
def array(files: File*): Array[File] = toArray(files.toList)
}

View File

@ -16,7 +16,8 @@ trait Provider extends NotNull
def parentLoader: ClassLoader
def lockFile: File
def classpath = Provider.getJars(baseDirectories)
def classpath: Array[File] = Provider.getJars(baseDirectories)
def fullClasspath:Array[File] = concat(classpath, extraClasspath)
def retrieveFailed: Nothing = fail("")
def retrieveCorrupt(missing: Iterable[String]): Nothing = fail(": missing " + missing.mkString(", "))
@ -47,8 +48,8 @@ trait Provider extends NotNull
}
def createLoader =
{
val fullClasspath = classpath ++ extraClasspath
(fullClasspath, new URLClassLoader(Provider.toURLs(fullClasspath), parentLoader) )
val full = fullClasspath
(full, new URLClassLoader(Provider.toURLs(full), parentLoader) )
}
}
}
@ -56,7 +57,7 @@ trait Provider extends NotNull
object Provider
{
def getJars(directories: List[File]): Array[File] = toArray(directories.flatMap(directory => wrapNull(directory.listFiles(JarFilter))))
def wrapNull(a: Array[File]): Array[File] = if(a == null) Array() else a
def wrapNull(a: Array[File]): Array[File] = if(a == null) new Array[File](0) else a
object JarFilter extends FileFilter
{

View File

@ -92,7 +92,7 @@ final class Update(config: UpdateConfiguration)
// the actual module id here is not that important
val moduleID = new DefaultModuleDescriptor(createID(SbtOrg, "boot-" + target.tpe, "1.0"), "release", null, false)
moduleID.setLastModified(System.currentTimeMillis)
moduleID.addConfiguration(new IvyConfiguration(DefaultIvyConfiguration, PUBLIC, "", Array(), true, null))
moduleID.addConfiguration(new IvyConfiguration(DefaultIvyConfiguration, PUBLIC, "", new Array(0), true, null))
// add dependencies based on which target needs updating
target match
{

View File

@ -4,11 +4,53 @@ import org.scalacheck._
import Prop._
import java.io.File
/** These mainly test that things work in the uncontested case and that no OverlappingFileLockExceptions occur.
* There is no real locking testing, just the coordination of locking.*/
object LocksTest extends Properties("Locks")
{
property("Lock in nonexisting directory") =
property("Lock in nonexisting directory") = spec {
FileUtilities.withTemporaryDirectory { dir =>
val lockFile = new File(dir, "doesntexist/lock")
Locks(lockFile, new java.util.concurrent.Callable[Boolean] { def call = true })
Locks(lockFile, callTrue)
}
}
property("Uncontested re-entrant lock") = spec {
FileUtilities.withTemporaryDirectory { dir =>
val lockFile = new File(dir, "lock")
Locks(lockFile, callLocked(lockFile)) &&
Locks(lockFile, callLocked(lockFile))
}
}
property("Uncontested double lock") = spec {
FileUtilities.withTemporaryDirectory { dir =>
val lockFileA = new File(dir, "lockA")
val lockFileB = new File(dir, "lockB")
Locks(lockFileA, callLocked(lockFileB)) &&
Locks(lockFileB, callLocked(lockFileA))
}
}
property("Contested single lock") = spec {
FileUtilities.withTemporaryDirectory { dir =>
val lockFile = new File(dir, "lock")
forkFold(2000){i => Locks(lockFile, callTrue) }
}
}
private def spec(f: => Boolean): Prop = Prop { _ => Result(if(f) True else False) }
private def call[T](impl: => T) = new java.util.concurrent.Callable[T] { def call = impl }
private def callLocked(lockFile: File) = call { Locks(lockFile, callTrue) }
private lazy val callTrue = call { true }
private def forkFold(n: Int)(impl: Int => Boolean): Boolean =
(true /: forkWait(n)(impl))(_ && _)
private def forkWait(n: Int)(impl: Int => Boolean): Iterable[Boolean] =
{
import scala.concurrent.ops.future
val futures = (0 until n).map { i => future { impl(i) } }
futures.toList.map(_())
}
}

View File

@ -1,5 +1,6 @@
package xsbt.boot
import java.io.File
import org.scalacheck._
object PreTest extends Properties("Pre")
@ -17,6 +18,11 @@ object PreTest extends Properties("Pre")
property("toBoolean") = Prop.forAll( (s: String) => trap(toBoolean(s)) == trap(java.lang.Boolean.parseBoolean(s)) )
property("toArray") = Prop.forAll( (list: List[Int]) => list.toArray deepEquals toArray(list) )
property("toArray") = Prop.forAll( (list: List[String]) => list.toArray deepEquals toArray(list) )
property("concat") = Prop.forAll(genFiles, genFiles) { (a: Array[File], b: Array[File]) => (a ++ b) sameElements concat(a, b) }
property("array") = Prop.forAll(genFiles) { (a: Array[File]) => array(a.toList : _*) sameElements Array(a: _*) }
implicit lazy val arbFile: Arbitrary[File] = Arbitrary { for(i <- Arbitrary.arbitrary[Int] ) yield new File(i.toString) }
implicit lazy val genFiles: Gen[Array[File]] = Arbitrary.arbitrary[Array[File]]
def trap[T](t: => T): Option[T] = try { Some(t) } catch { case e: Exception => None }
}