Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

- Stuart's improvements to triggered execution

- continue splitting original sbt module
 * separated process, testing modules
 * various IO, logging, classpath migration
 * split out javac interface
  • Loading branch information...
commit 6f3c69943505584f2db2800cd17f4eb9715d28d1 1 parent 37185c0
@harrah authored
Showing with 497 additions and 643 deletions.
  1. +17 −14 compile/AnalyzingCompiler.scala
  2. +0 −10 compile/CompileLogger.scala
  3. +5 −1 compile/CompilerArguments.scala
  4. +5 −2 compile/ComponentCompiler.scala
  5. +66 −0 compile/JavaCompiler.scala
  6. +1 −1  compile/NOTICE
  7. +6 −2 compile/RawCompiler.scala
  8. +3 −0  compile/discover/NOTICE
  9. +3 −0  compile/inc/NOTICE
  10. +12 −2 compile/inc/notes
  11. +1 −1  compile/interface/API.scala
  12. +3 −0  compile/persist/NOTICE
  13. +2 −4 ivy/src/test/scala/ComponentManagerTest.scala
  14. +1 −3 ivy/src/test/scala/TestIvyLogger.scala
  15. +4 −4 main/AggressiveCompile.scala
  16. +3 −3 main/AggressiveCompiler.scala
  17. +17 −9 project/build/XSbt.scala
  18. +0 −85 sbt/src/main/scala/sbt/Compile.scala
  19. +1 −4 sbt/src/main/scala/sbt/Logger.scala
  20. +2 −1  sbt/src/main/scala/sbt/Main.scala
  21. +0 −87 sbt/src/main/scala/sbt/Pack.scala
  22. +0 −31 sbt/src/main/scala/sbt/SourceModificationWatch.scala
  23. +0 −84 sbt/src/test/scala/sbt/FileUtilitiesSpecification.scala
  24. +0 −182 sbt/src/test/scala/sbt/ReflectSpecification.scala
  25. +3 −0  testing/NOTICE
  26. +11 −11 {sbt/src/main/scala/sbt → testing}/TestFramework.scala
  27. 0  {sbt/src/main/scala/sbt → testing}/TestReportListener.scala
  28. 0  {sbt/src/main/scala/sbt → testing}/impl/TestParser.scala
  29. 0  {sbt/src/main/scala/sbt → testing}/impl/TestStatusReporter.scala
  30. +2 −1  util/classpath/ClassLoaders.scala
  31. +24 −43 {sbt/src/main/scala/sbt → util/classpath}/ClasspathUtilities.scala
  32. +2 −1  util/classpath/DualLoader.scala
  33. 0  {sbt/src/main/scala/sbt → util/classpath}/ModuleUtilities.scala
  34. +1 −1  util/classpath/NOTICE
  35. +1 −1  {sbt/src/main/scala/sbt → util/classpath}/ReflectUtilities.scala
  36. +4 −1 {compile → util/classpath}/ScalaInstance.scala
  37. +3 −0  util/complete/NOTICE
  38. +19 −4 util/io/IO.scala
  39. +79 −0 util/io/Pack.scala
  40. +2 −1  util/io/Path.scala
  41. +37 −0 util/io/SourceModificationWatch.scala
  42. +78 −0 util/io/src/test/scala/FileUtilitiesSpecification.scala
  43. +3 −3 util/log/BufferedLogger.scala
  44. +24 −0 util/log/FullLogger.scala
  45. +19 −11 util/log/Logger.scala
  46. +2 −2 util/log/LoggerWriter.scala
  47. +0 −2  {sbt/src/main/scala/sbt → util/process}/Process.scala
  48. +4 −4 {sbt/src/main/scala/sbt/impl → util/process}/ProcessImpl.scala
  49. +14 −15 {sbt/src/test/scala/sbt → util/process/src/test/scala}/ProcessSpecification.scala
  50. +13 −12 {sbt/src/test/scala/sbt → util/process/src/test/scala}/TestedProcess.scala
View
31 compile/AnalyzingCompiler.scala
@@ -1,6 +1,9 @@
-package xsbt
+/* sbt -- Simple Build Tool
+ * Copyright 2009, 2010 Mark Harrah
+ */
+package sbt
+package compile
- import sbt.ComponentManager
import xsbti.{AnalysisCallback, Logger => xLogger}
import java.io.File
import java.net.{URL, URLClassLoader}
@@ -9,34 +12,34 @@ package xsbt
* provided by scalaInstance. This class requires a ComponentManager in order to obtain the interface code to scalac and
* the analysis plugin. Because these call Scala code for a different Scala version than the one used for this class, they must
* be compiled for the version of Scala being used.*/
-class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: ComponentManager, val cp: ClasspathOptions, log: CompileLogger) extends NotNull
+class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: ComponentManager, val cp: ClasspathOptions, log: Logger) extends NotNull
{
- def this(scalaInstance: ScalaInstance, manager: ComponentManager, log: CompileLogger) = this(scalaInstance, manager, ClasspathOptions.auto, log)
- def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: CompileLogger)
+ def this(scalaInstance: ScalaInstance, manager: ComponentManager, log: Logger) = this(scalaInstance, manager, ClasspathOptions.auto, log)
+ def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: Logger)
{
val arguments = (new CompilerArguments(scalaInstance, cp))(sources, classpath, outputDirectory, options)
compile(arguments, callback, maximumErrors, log)
}
- def compile(arguments: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: CompileLogger)
+ def compile(arguments: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: Logger)
{
call("xsbt.CompilerInterface", log)(
classOf[Array[String]], classOf[AnalysisCallback], classOf[Int], classOf[xLogger] ) (
arguments.toArray[String] : Array[String], callback, maximumErrors: java.lang.Integer, log )
}
- def doc(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], maximumErrors: Int, log: CompileLogger): Unit =
+ def doc(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], maximumErrors: Int, log: Logger): Unit =
{
val arguments = (new CompilerArguments(scalaInstance, cp))(sources, classpath, outputDirectory, options)
call("xsbt.ScaladocInterface", log) (classOf[Array[String]], classOf[Int], classOf[xLogger]) (arguments.toArray[String] : Array[String], maximumErrors: java.lang.Integer, log)
}
- def console(classpath: Seq[File], options: Seq[String], initialCommands: String, log: CompileLogger): Unit =
+ def console(classpath: Seq[File], options: Seq[String], initialCommands: String, log: Logger): Unit =
{
val arguments = new CompilerArguments(scalaInstance, cp)
val classpathString = CompilerArguments.absString(arguments.finishClasspath(classpath))
val bootClasspath = if(cp.autoBoot) arguments.createBootClasspath else ""
call("xsbt.ConsoleInterface", log) (classOf[Array[String]], classOf[String], classOf[String], classOf[String], classOf[xLogger]) (options.toArray[String]: Array[String], bootClasspath, classpathString, initialCommands, log)
}
- def force(log: CompileLogger): Unit = getInterfaceJar(log)
- private def call(interfaceClassName: String, log: CompileLogger)(argTypes: Class[_]*)(args: AnyRef*)
+ def force(log: Logger): Unit = getInterfaceJar(log)
+ private def call(interfaceClassName: String, log: Logger)(argTypes: Class[_]*)(args: AnyRef*)
{
val interfaceClass = getInterfaceClass(interfaceClassName, log)
val interface = interfaceClass.newInstance.asInstanceOf[AnyRef]
@@ -50,20 +53,20 @@ class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: Component
val dual = createDualLoader(scalaInstance.loader, getClass.getClassLoader) // this goes to scalaLoader for scala classes and sbtLoader for xsbti classes
new URLClassLoader(Array(interfaceJar.toURI.toURL), dual)
}
- private def getInterfaceClass(name: String, log: CompileLogger) = Class.forName(name, true, loader)
- private def getInterfaceJar(log: CompileLogger) =
+ private def getInterfaceClass(name: String, log: Logger) = Class.forName(name, true, loader)
+ private def getInterfaceJar(log: Logger) =
{
// this is the instance used to compile the interface component
val componentCompiler = newComponentCompiler(log)
log.debug("Getting " + ComponentCompiler.compilerInterfaceID + " from component compiler for Scala " + scalaInstance.version)
componentCompiler(ComponentCompiler.compilerInterfaceID)
}
- def newComponentCompiler(log: CompileLogger) = new ComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager)
+ def newComponentCompiler(log: Logger) = new ComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager)
protected def createDualLoader(scalaLoader: ClassLoader, sbtLoader: ClassLoader): ClassLoader =
{
val xsbtiFilter = (name: String) => name.startsWith("xsbti.")
val notXsbtiFilter = (name: String) => !xsbtiFilter(name)
- new DualLoader(scalaLoader, notXsbtiFilter, x => true, sbtLoader, xsbtiFilter, x => false)
+ new classpath.DualLoader(scalaLoader, notXsbtiFilter, x => true, sbtLoader, xsbtiFilter, x => false)
}
override def toString = "Analyzing compiler (Scala " + scalaInstance.actualVersion + ")"
}
View
10 compile/CompileLogger.scala
@@ -1,10 +0,0 @@
-package xsbt
-
-trait CompileLogger extends xsbti.Logger with NotNull
-{
- def info(msg: => String)
- def debug(msg: => String)
- def warn(msg: => String)
- def error(msg: => String)
- def trace(t: => Throwable)
-}
View
6 compile/CompilerArguments.scala
@@ -1,4 +1,8 @@
-package xsbt
+/* sbt -- Simple Build Tool
+ * Copyright 2009, 2010 Mark Harrah
+ */
+package sbt
+package compile
import java.io.File
import CompilerArguments.{abs, absString}
View
7 compile/ComponentCompiler.scala
@@ -1,7 +1,10 @@
-package xsbt
+/* sbt -- Simple Build Tool
+ * Copyright 2009, 2010 Mark Harrah
+ */
+package sbt
+package compile
import java.io.File
-import sbt.{ComponentManager, IfMissing, InvalidComponent}
object ComponentCompiler
{
View
66 compile/JavaCompiler.scala
@@ -0,0 +1,66 @@
+/* sbt -- Simple Build Tool
+ * Copyright 2008, 2009, 2010 Mark Harrah, Seth Tisue
+ */
+package sbt
+package compile
+
+ import java.io.File
+
+trait JavaCompiler
+{
+ def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger): Unit
+}
+object JavaCompiler
+{
+ def construct(f: (Seq[String], Logger) => Int, cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaCompiler =
+ new JavaCompiler {
+ def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger) {
+ val augmentedClasspath = if(cp.autoBoot) classpath ++ Seq(scalaInstance.libraryJar) else classpath
+ val javaCp = new ClasspathOptions(false, cp.compiler, false)
+ val arguments = (new CompilerArguments(scalaInstance, javaCp))(sources, augmentedClasspath, outputDirectory, options)
+ log.debug("running javac with arguments:\n\t" + arguments.mkString("\n\t"))
+ val code: Int = f(arguments, log)
+ log.debug("javac returned exit code: " + code)
+ if( code != 0 ) throw new CompileFailed(arguments.toArray, "javac returned nonzero exit code")
+ }
+ }
+ def directOrFork(cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaCompiler = construct(directOrForkJavac, cp, scalaInstance)
+ def direct(cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaCompiler = construct(directJavac, cp, scalaInstance)
+ def fork(cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaCompiler = construct(forkJavac, cp, scalaInstance)
+
+ val directOrForkJavac = (arguments: Seq[String], log: Logger) =>
+ try { directJavac(arguments, log) }
+ catch { case e: ClassNotFoundException =>
+ log.debug("com.sun.tools.javac.Main not found; forking javac instead")
+ forkJavac(arguments, log)
+ }
+
+ val forkJavac = (arguments: Seq[String], log: Logger) =>
+ {
+ def externalJavac(argFile: File) = Process("javac", ("@" + normalizeSlash(argFile.getAbsolutePath)) :: Nil) ! log
+ withArgumentFile(arguments)(externalJavac)
+ }
+ val directJavac = (arguments: Seq[String], log: Logger) =>
+ {
+ val writer = new java.io.PrintWriter(new LoggerWriter(log, Level.Error))
+ val argsArray = arguments.toArray
+ val javac = Class.forName("com.sun.tools.javac.Main")
+ log.debug("Calling javac directly.")
+ javac.getDeclaredMethod("compile", classOf[Array[String]], classOf[java.io.PrintWriter])
+ .invoke(null, argsArray, writer)
+ .asInstanceOf[java.lang.Integer]
+ .intValue
+ }
+ def withArgumentFile[T](args: Seq[String])(f: File => T): T =
+ {
+ import IO.{Newline, withTemporaryDirectory, write}
+ withTemporaryDirectory { tmp =>
+ val argFile = new File(tmp, "argfile")
+ write(argFile, args.map(escapeSpaces).mkString(Newline))
+ f(argFile)
+ }
+ }
+ // javac's argument file seems to allow naive space escaping with quotes. escaping a quote with a backslash does not work
+ def escapeSpaces(s: String): String = '\"' + normalizeSlash(s) + '\"'
+ def normalizeSlash(s: String) = s.replace(File.separatorChar, '/')
+}
View
2  compile/NOTICE
@@ -1,3 +1,3 @@
Simple Build Tool: Compile Component
-Copyright 2009, 2010 Mark Harrah, Jason Zaugg
+Copyright 2009, 2010 Mark Harrah, Seth Tisue, Jason Zaugg
Licensed under BSD-style license (see LICENSE)
View
8 compile/RawCompiler.scala
@@ -1,4 +1,8 @@
-package xsbt
+/* sbt -- Simple Build Tool
+ * Copyright 2009, 2010 Mark Harrah
+ */
+package sbt
+package compile
import java.io.File
@@ -6,7 +10,7 @@ package xsbt
* is used, for example, to compile the interface/plugin code.
* If `explicitClasspath` is true, the bootclasspath and classpath are not augmented. If it is false,
* the scala-library.jar from `scalaInstance` is put on bootclasspath and the scala-compiler jar goes on the classpath.*/
-class RawCompiler(val scalaInstance: ScalaInstance, cp: ClasspathOptions, log: CompileLogger)
+class RawCompiler(val scalaInstance: ScalaInstance, cp: ClasspathOptions, log: Logger)
{
def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])
{
View
3  compile/discover/NOTICE
@@ -0,0 +1,3 @@
+Simple Build Tool: Discovery Component
+Copyright 2010 Mark Harrah
+Licensed under BSD-style license (see LICENSE)
View
3  compile/inc/NOTICE
@@ -0,0 +1,3 @@
+Simple Build Tool: Incremental Logic Component
+Copyright 2010 Mark Harrah
+Licensed under BSD-style license (see LICENSE)
View
14 compile/inc/notes
@@ -4,8 +4,18 @@ Tradiationally, there has been a main group and a test group.
Each Analysis is associated with one or more classpath entries. Typically, it will be associated with the output directory and/or any artifacts produced from that output directory.
-Need to be able to process Source and extract classes {C} s.t. C <: D for D in {D} or C or one of its non-private methods is annotated with annotation A in {A} or C.main(args: Array[String]) exists
-
For Java sources, need to write a (File, Set[File]) => Source function that reads an API from a class file. The compile function passed to IncrementalCompile needs to handle compiling Java sources in the proper order
Need to handle entries removed from classpath. Could be done similarly to how Locate is used for getting the API for a dependency. In this case, we'd get the Stamp for a binary dependency.
+
+Post-analysis
+ - need to handle inherited definitions
+
+Need builder component:
+ Processor[D]
+ def process(command: String, arg: String, current: State[D]): Result[State[D]]
+ Initial[D]
+ def init: State[D]
+ State[D]
+ value: D
+ processors: Map[String, Processor[D]]
View
2  compile/interface/API.scala
@@ -300,7 +300,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
}
def isTopLevel(sym: Symbol): Boolean =
(sym ne null) && (sym != NoSymbol) && !sym.isImplClass && !sym.isNestedClass && sym.isStatic &&
- !sym.hasFlag(Flags.SYNTHETIC) && !sym.hasFlag(Flags.JAVA)
+ !sym.hasFlag(Flags.SYNTHETIC)// && !sym.hasFlag(Flags.JAVA)
}
// In 2.8, attributes is renamed to annotations
View
3  compile/persist/NOTICE
@@ -0,0 +1,3 @@
+Simple Build Tool: Analysis Store Component
+Copyright 2010 Mark Harrah
+Licensed under BSD-style license (see LICENSE)
View
6 ivy/src/test/scala/ComponentManagerTest.scala
@@ -1,10 +1,8 @@
package sbt
-import xsbt.{BufferedLogger, FileUtilities}
-
import java.io.File
import org.specs._
-import FileUtilities.{createDirectory, delete, touch, withTemporaryDirectory}
+import IO.{createDirectory, delete, touch, withTemporaryDirectory}
import org.apache.ivy.util.ChecksumHelper
import IfMissing.Fail
@@ -76,7 +74,7 @@ object ComponentManagerTest extends Specification
manager.define(id, files)
f(files)
}
- private def writeRandomContent(file: File) = FileUtilities.write(file, randomString)
+ private def writeRandomContent(file: File) = IO.write(file, randomString)
private def randomString = "asdf"
private def withManager[T](f: ComponentManager => T): T =
TestIvyLogger( logger => withTemporaryDirectory { temp => f(new ComponentManager(xsbt.boot.Locks, new xsbt.boot.ComponentProvider(temp), logger)) } )
View
4 ivy/src/test/scala/TestIvyLogger.scala
@@ -1,8 +1,6 @@
package sbt
-import xsbt.{BufferedLogger, ConsoleLogger, Level}
-
-class TestIvyLogger extends BufferedLogger(new ConsoleLogger) with IvyLogger { def verbose(msg: => String) = info(msg) }
+class TestIvyLogger extends BufferedLogger(new ConsoleLogger) with IvyLogger
object TestIvyLogger
{
def apply[T](f: IvyLogger => T): T =
View
8 main/AggressiveCompile.scala
@@ -6,7 +6,7 @@ package sbt
import inc._
import java.io.File
- import xsbt.{AnalyzingCompiler, CompileLogger, CompilerArguments}
+ import sbt.compile.{AnalyzingCompiler, CompilerArguments}
import xsbti.api.Source
import xsbti.AnalysisCallback
import CompileSetup._
@@ -18,7 +18,7 @@ final class CompileConfiguration(val sources: Seq[File], val classpath: Seq[File
class AggressiveCompile(cacheDirectory: File)
{
- def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], compiler: AnalyzingCompiler, log: CompileLogger): Analysis =
+ def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], compiler: AnalyzingCompiler, log: Logger): Analysis =
{
val setup = new CompileSetup(outputDirectory, new CompileOptions(options), compiler.scalaInstance.actualVersion, CompileOrder.Mixed)
compile1(sources, classpath, setup, store, Map.empty, compiler, log)
@@ -27,7 +27,7 @@ class AggressiveCompile(cacheDirectory: File)
def withBootclasspath(args: CompilerArguments, classpath: Seq[File]): Seq[File] =
args.bootClasspath ++ classpath
- def compile1(sources: Seq[File], classpath: Seq[File], setup: CompileSetup, store: AnalysisStore, analysis: Map[File, Analysis], compiler: AnalyzingCompiler, log: CompileLogger): Analysis =
+ def compile1(sources: Seq[File], classpath: Seq[File], setup: CompileSetup, store: AnalysisStore, analysis: Map[File, Analysis], compiler: AnalyzingCompiler, log: Logger): Analysis =
{
val (previousAnalysis, previousSetup) = extract(store.get())
val config = new CompileConfiguration(sources, classpath, previousAnalysis, previousSetup, setup, analysis.get _, 100, compiler)
@@ -35,7 +35,7 @@ class AggressiveCompile(cacheDirectory: File)
store.set(result, setup)
result
}
- def compile2(config: CompileConfiguration, log: CompileLogger)(implicit equiv: Equiv[CompileSetup]): Analysis =
+ def compile2(config: CompileConfiguration, log: Logger)(implicit equiv: Equiv[CompileSetup]): Analysis =
{
import config._
import currentSetup._
View
6 main/AggressiveCompiler.scala
@@ -3,7 +3,7 @@
*/
package sbt
- import xsbt.{AnalyzingCompiler, CompileLogger, ScalaInstance}
+ import sbt.compile.AnalyzingCompiler
import java.io.File
import System.{currentTimeMillis => now}
import Path._
@@ -23,13 +23,13 @@ class AggressiveCompiler extends xsbti.AppMain
def run(command: String, args: List[String], cwd: Path, app: xsbti.AppProvider): Boolean =
{
val launcher = app.scalaProvider.launcher
- val sources = cwd ** "*.scala"
+ val sources = cwd ** ("*.scala" | "*.java")
val target = cwd / "target"
val outputDirectory = target / "classes"
val classpath = outputDirectory +++ (cwd * "*.jar") +++(cwd * (-"project")).descendentsExcept( "*.jar", "project" || HiddenFileFilter)
val cacheDirectory = target / "cache"
val options = args.tail.toSeq
- val log = new ConsoleLogger with CompileLogger with sbt.IvyLogger
+ val log = new ConsoleLogger with Logger with sbt.IvyLogger
val componentManager = new ComponentManager(launcher.globalLock, app.components, log)
val compiler = new AnalyzingCompiler(ScalaInstance(args.head, launcher), componentManager, log)
View
26 project/build/XSbt.scala
@@ -12,26 +12,30 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths
val interfaceSub = project("interface", "Interface", new InterfaceProject(_))
val apiSub = baseProject(compilePath / "api", "API", interfaceSub)
+ // util
val controlSub = baseProject(utilPath / "control", "Control")
val collectionSub = testedBase(utilPath / "collection", "Collections")
val ioSub = testedBase(utilPath / "io", "IO", controlSub)
- val classpathSub = baseProject(utilPath / "classpath", "Classpath")
+ val classpathSub = baseProject(utilPath / "classpath", "Classpath", launchInterfaceSub, ioSub)
val classfileSub = testedBase(utilPath / "classfile", "Classfile", ioSub, interfaceSub)
val completeSub = testedBase(utilPath / "complete", "Completion", ioSub)
-
- val ivySub = project("ivy", "Ivy", new IvyProject(_), interfaceSub, launchInterfaceSub)
val logSub = project(utilPath / "log", "Logging", new LogProject(_), interfaceSub)
- val datatypeSub = baseProject("util" /"datatype", "Datatype Generator", ioSub)
+ val datatypeSub = baseProject(utilPath /"datatype", "Datatype Generator", ioSub)
+ val processSub = project(utilPath /"process", "Process", new Base(_) with TestWithIO, ioSub, logSub)
+ // intermediate-level modules
+ val ivySub = project("ivy", "Ivy", new IvyProject(_), interfaceSub, launchInterfaceSub, logSub)
+ val testingSub = project("testing", "Testing", new TestingProject(_), ioSub, classpathSub, logSub)
+ val taskSub = testedBase(tasksPath, "Tasks", controlSub, collectionSub)
+ val cacheSub = project(cachePath, "Cache", new CacheProject(_), ioSub, collectionSub)
+
+ // compilation/discovery related modules
val compileInterfaceSub = project(compilePath / "interface", "Compiler Interface", new CompilerInterfaceProject(_), interfaceSub)
val compileIncrementalSub = testedBase(compilePath / "inc", "Incremental Compiler", collectionSub, apiSub, ioSub)
val discoverySub = testedBase(compilePath / "discover", "Discovery", compileIncrementalSub, apiSub)
val compilePersistSub = project(compilePath / "persist", "Persist", new PersistProject(_), compileIncrementalSub, apiSub)
val compilerSub = project(compilePath, "Compile", new CompileProject(_),
- launchInterfaceSub, interfaceSub, ivySub, ioSub, classpathSub, compileInterfaceSub)
-
- val taskSub = testedBase(tasksPath, "Tasks", controlSub, collectionSub)
- val cacheSub = project(cachePath, "Cache", new CacheProject(_), ioSub, collectionSub)
+ launchInterfaceSub, interfaceSub, ivySub, ioSub, classpathSub, compileInterfaceSub, logSub, processSub)
val altCompilerSub = baseProject("main", "Alternate Compiler Test", compileIncrementalSub, compilerSub, ioSub, logSub, discoverySub, compilePersistSub)
@@ -40,7 +44,7 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths
val trackingSub = baseProject(cachePath / "tracking", "Tracking", cacheSub)
- val sbtSub = project(sbtPath, "Simple Build Tool", new SbtProject(_) {}, compilerSub, launchInterfaceSub)
+ val sbtSub = project(sbtPath, "Simple Build Tool", new SbtProject(_) {}, compilerSub, launchInterfaceSub, testingSub, cacheSub, taskSub)
val installerSub = project(sbtPath / "install", "Installer", new InstallerProject(_) {}, sbtSub)
lazy val dist = task { None } dependsOn(launchSub.proguard, sbtSub.publishLocal, installerSub.publishLocal)
@@ -123,6 +127,10 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths
def seePaths(noticeString: String): List[Path] = seeRegex.findAllIn(noticeString).matchData.map(d => licensePath(d.group(1))).toList
def extractLicenses = if(!notice.exists) Nil else FileUtilities.readString(notice asFile, log).fold(_ => { log.warn("Could not read NOTICE"); Nil} , seePaths _)
}
+ class TestingProject(info: ProjectInfo) extends Base(info)
+ {
+ val testInterface = "org.scala-tools.testing" % "test-interface" % "0.5"
+ }
class CompileProject(info: ProjectInfo) extends Base(info) with TestWithLog with TestWithLaunch
{
override def testCompileAction = super.testCompileAction dependsOn(compileInterfaceSub.`package`, interfaceSub.`package`)
View
85 sbt/src/main/scala/sbt/Compile.scala
@@ -6,10 +6,6 @@ package sbt
import java.io.File
import xsbt.{AnalyzingCompiler, CompileFailed, CompilerArguments, ScalaInstance}
-object CompileOrder extends Enumeration
-{
- val Mixed, JavaThenScala, ScalaThenJava = Value
-}
sealed abstract class CompilerCore
{
@@ -75,50 +71,6 @@ final class Compile(maximumErrors: Int, compiler: AnalyzingCompiler, analysisCal
val callbackInterface = new AnalysisInterface(analysisCallback, baseDirectory, outputDirectory)
compiler(Set() ++ sources, Set() ++ classpath, outputDirectory, options, callbackInterface, maximumErrors, log)
}
- protected def processJava(sources: Set[File], classpath: Set[File], outputDirectory: File, options: Seq[String], log: Logger)
- {
- val augmentedClasspath = if(compiler.cp.autoBoot) classpath + compiler.scalaInstance.libraryJar else classpath
- val cp = new xsbt.ClasspathOptions(false, compiler.cp.compiler, false)
- val arguments = (new CompilerArguments(compiler.scalaInstance, cp))(sources, augmentedClasspath, outputDirectory, options)
- log.debug("running javac with arguments:\n\t" + arguments.mkString("\n\t"))
- val code: Int =
- try { directJavac(arguments, log) }
- catch { case e: ClassNotFoundException => forkJavac(arguments, log) }
- log.debug("javac returned exit code: " + code)
- if( code != 0 ) throw new CompileFailed(arguments.toArray, "javac returned nonzero exit code")
- }
- private def forkJavac(arguments: Seq[String], log: Logger): Int =
- {
- log.debug("com.sun.tools.javac.Main not found; forking javac instead")
- def externalJavac(argFile: File) = Process("javac", ("@" + normalizeSlash(argFile.getAbsolutePath)) :: Nil) ! log
- withArgumentFile(arguments)(externalJavac)
- }
- private def directJavac(arguments: Seq[String], log: Logger): Int =
- {
- val writer = new java.io.PrintWriter(new LoggerWriter(log, Level.Error))
- val argsArray = arguments.toArray
- val javac = Class.forName("com.sun.tools.javac.Main")
- log.debug("Calling javac directly.")
- javac.getDeclaredMethod("compile", classOf[Array[String]], classOf[java.io.PrintWriter])
- .invoke(null, argsArray, writer)
- .asInstanceOf[java.lang.Integer]
- .intValue
- }
-}
-trait WithArgumentFile extends NotNull
-{
- def withArgumentFile[T](args: Seq[String])(f: File => T): T =
- {
- import xsbt.FileUtilities._
- withTemporaryDirectory { tmp =>
- val argFile = new File(tmp, "argfile")
- write(argFile, args.map(escapeSpaces).mkString(FileUtilities.Newline))
- f(argFile)
- }
- }
- // javac's argument file seems to allow naive space escaping with quotes. escaping a quote with a backslash does not work
- def escapeSpaces(s: String): String = '\"' + normalizeSlash(s) + '\"'
- def normalizeSlash(s: String) = s.replace(File.separatorChar, '/')
}
final class Scaladoc(maximumErrors: Int, compiler: AnalyzingCompiler) extends CompilerCore
{
@@ -142,40 +94,3 @@ final class Console(compiler: AnalyzingCompiler) extends NotNull
JLine.withJLine( Run.executeTrapExit(console0, log) )
}
}
-
-private final class AnalysisInterface(delegate: AnalysisCallback, basePath: Path, outputDirectory: File) extends xsbti.AnalysisCallback with NotNull
-{
- val outputPath = Path.fromFile(outputDirectory)
- def superclassNames = delegate.superclassNames.toSeq.toArray[String]
- def annotationNames = delegate.annotationNames.toSeq.toArray[String]
- def superclassNotFound(superclassName: String) = delegate.superclassNotFound(superclassName)
- def beginSource(source: File) = delegate.beginSource(srcPath(source))
-
- def foundSubclass(source: File, subclassName: String, superclassName: String, isModule: Boolean) =
- delegate.foundSubclass(srcPath(source), subclassName, superclassName, isModule)
- def foundAnnotated(source: File, className: String, annotationName: String, isModule: Boolean) =
- delegate.foundAnnotated(srcPath(source), className, annotationName, isModule)
- def foundApplication(source: File, className: String) = delegate.foundApplication(srcPath(source), className)
-
- def sourceDependency(dependsOn: File, source: File) =
- delegate.sourceDependency(srcPath(dependsOn), srcPath(source))
- def jarDependency(jar: File, source: File) = delegate.jarDependency(jar, srcPath(source))
- def generatedClass(source: File, clazz: File) = delegate.generatedClass(srcPath(source), classPath(clazz))
- def endSource(source: File) = delegate.endSource(srcPath(source))
-
- def classDependency(clazz: File, source: File) =
- {
- val sourcePath = srcPath(source)
- Path.relativize(outputPath, clazz) match
- {
- case None => // dependency is a class file outside of the output directory
- delegate.classDependency(clazz, sourcePath)
- case Some(relativeToOutput) => // dependency is a product of a source not included in this compilation
- delegate.productDependency(relativeToOutput, sourcePath)
- }
- }
- def relativizeOrAbs(base: Path, file: File) = Path.relativize(base, file).getOrElse(Path.fromFile(file))
- def classPath(file: File) = relativizeOrAbs(outputPath, file)
- def srcPath(file: File) = relativizeOrAbs(basePath, file)
- def api(file: File, source: xsbti.api.Source) = delegate.api(srcPath(file), source)
-}
View
5 sbt/src/main/scala/sbt/Logger.scala
@@ -5,9 +5,6 @@ package sbt
import scala.collection.mutable.{Buffer, HashMap, ListBuffer}
-
-trait Logger extends AbstractLogger with xsbt.CompileLogger with IvyLogger
-
/** A logger that can buffer the logging done on it by currently executing Thread and
* then can flush the buffer to the delegate logger provided in the constructor. Use
* 'startRecording' to start buffering and then 'play' from to flush the buffer for the
@@ -19,7 +16,7 @@ trait Logger extends AbstractLogger with xsbt.CompileLogger with IvyLogger
*
* This logger is thread-safe.
* */
-final class BufferedLogger(delegate: AbstractLogger) extends Logger
+final class BufferedLogger(delegate: Logger) extends AbstractLogger
{
override lazy val ansiCodesSupported = delegate.ansiCodesSupported
private[this] val buffers = wrap.Wrappers.weakMap[Thread, Buffer[LogEvent]]
View
3  sbt/src/main/scala/sbt/Main.scala
@@ -740,7 +740,8 @@ class xMain extends xsbti.AppMain
if(actionValid)
{
var count = 0
- SourceModificationWatch.watchUntil(project, ContinuousCompilePollDelaySeconds)(shouldTerminate)
+ val sourcesFinder: PathFinder = (Path.emptyPathFinder /: project.topologicalSort)(_ +++ _.watchPaths)
+ SourceModificationWatch.watchUntil(sourcesFinder, ContinuousCompilePollDelaySeconds)(shouldTerminate)
{
count += 1
handleAction(project, action)
View
87 sbt/src/main/scala/sbt/Pack.scala
@@ -1,87 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2009 Mark Harrah
- */
-package sbt
-
-import java.io.{File, FileOutputStream}
-import java.util.jar.{JarEntry, JarFile, JarOutputStream, Pack200}
-import scala.collection.Map
-import FileUtilities._
-
-object Pack
-{
- def pack(jarPath: Path, out: Path, log: Logger): Option[String] = pack(jarPath, out, defaultPackerOptions, log)
- def pack(jarPath: Path, out: Path, options: Map[String, String], log: Logger): Option[String] =
- {
- val packer = Pack200.newPacker
- val properties = new wrap.MutableMapWrapper(packer.properties)
- properties ++= options
-
- OpenResource.jarFile(false).ioOption(jarPath.asFile, "applying pack200 compression to jar", log) { f =>
- writeStream(out.asFile, log) { stream =>
- packer.pack(f, stream)
- None
- }
- }
- }
- def unpack(packedPath: Path, toJarPath: Path, log: Logger): Option[String] =
- {
- val unpacker = Pack200.newUnpacker
- writeStream(toJarPath.asFile, log) { fileStream =>
- val jarOut = new JarOutputStream(fileStream)
- Control.trapUnitAndFinally("Error unpacking '" + packedPath + "': ", log)
- { unpacker.unpack(packedPath.asFile, jarOut); None }
- { jarOut.close() }
- }
- }
- def defaultPackerOptions: Map[String, String] = scala.collection.immutable.Map()
-}
-
-import java.net.URL
-/** This is somewhat of a mess and is not entirely correct. jarsigner doesn't work properly
-* on scalaz and it is difficult to determine whether a jar is both signed and valid. */
-object SignJar
-{
- final class SignOption private[SignJar](val toList: List[String], val signOnly: Boolean) extends NotNull
- {
- override def toString = toList.mkString(" ")
- }
- def keyStore(url: URL) = new SignOption("-keystore" :: url.toExternalForm :: Nil, true)
- def signedJar(p: Path) = new SignOption("-signedjar" :: p.asFile.getAbsolutePath :: Nil, true)
- def verbose = new SignOption("-verbose" :: Nil, false)
- def sigFile(name: String) = new SignOption("-sigfile" :: name :: Nil, true)
- def storeType(t: String) = new SignOption("-storetype" :: t :: Nil, false)
- def provider(p: String) = new SignOption("-provider" :: p :: Nil, false)
- def providerName(p: String) = new SignOption("-providerName" :: p :: Nil, false)
- def storePassword(p: String) = new SignOption("-storepass" :: p :: Nil, true)
- def keyPassword(p: String) = new SignOption("-keypass" :: p :: Nil, true)
-
- private def VerifyOption = "-verify"
-
- /** Uses jarsigner to sign the given jar. */
- def sign(jarPath: Path, alias: String, options: Seq[SignOption], log: Logger): Option[String] =
- {
- require(!alias.trim.isEmpty, "Alias cannot be empty")
- val arguments = options.toList.flatMap(_.toList) ::: jarPath.asFile.getAbsolutePath :: alias :: Nil
- execute("Signed " + jarPath, "signing", arguments, log)
- }
- /** Uses jarsigner to verify the given jar.*/
- def verify(jarPath: Path, options: Seq[SignOption], log: Logger): Option[String] =
- {
- val arguments = options.filter(!_.signOnly).toList.flatMap(_.toList) ::: VerifyOption :: jarPath.asFile.getAbsolutePath :: Nil
- execute("Verified " + jarPath, "verifying", arguments, log)
- }
- private def execute(successMessage: String, action: String, arguments: List[String], log: Logger): Option[String] =
- {
- val exitCode = Process(CommandName, arguments) ! log
- if(exitCode == 0)
- {
- log.debug(successMessage)
- None
- }
- else
- Some("Error " + action + " jar (exit code was " + exitCode + ".)")
- }
-
- private val CommandName = "jarsigner"
-}
View
31 sbt/src/main/scala/sbt/SourceModificationWatch.scala
@@ -1,31 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2009 Mikko Peltonen, Mark Harrah
- */
-package sbt
-
-object SourceModificationWatch
-{
- def watchUntil(project: Project, pollDelaySec: Int)(terminationCondition: => Boolean)(onSourcesModified: => Unit)
- {
- def sourceFiles: Iterable[java.io.File] = sourcesFinder.getFiles
- def sourcesFinder: PathFinder = (Path.emptyPathFinder /: project.topologicalSort)(_ +++ _.watchPaths)
- def loop(lastCallbackCallTime: Long, previousFileCount: Int)
- {
- val (lastModifiedTime, fileCount) = sourceFiles.foldLeft((0L, 0)){(acc, file) => (Math.max(acc._1, file.lastModified), acc._2 + 1)}
- val newCallbackCallTime =
- // check if sources are modified
- if (lastModifiedTime > lastCallbackCallTime || previousFileCount != fileCount)
- {
- val now = System.currentTimeMillis
- onSourcesModified
- now
- }
- else
- lastCallbackCallTime
- Thread.sleep(pollDelaySec * 1000)
- if(!terminationCondition)
- loop(newCallbackCallTime, fileCount)
- }
- loop(0L, 0)
- }
-}
View
84 sbt/src/test/scala/sbt/FileUtilitiesSpecification.scala
@@ -1,84 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah
- */
-package sbt
-
-import org.scalacheck._
-import java.io.File
-
-object WriteContentSpecification extends Properties("Write content")
-{
- val log = new ConsoleLogger
- log.setLevel(Level.Warn)
-
- specify("Roundtrip string", writeAndCheckString _)
- specify("Roundtrip bytes", writeAndCheckBytes _)
- specify("Write string overwrites", overwriteAndCheckStrings _)
- specify("Write bytes overwrites", overwriteAndCheckBytes _)
- specify("Append string appends", appendAndCheckStrings _)
- specify("Append bytes appends", appendAndCheckBytes _)
- property("Unzip doesn't stack overflow") = largeUnzip() match { case Some(msg) => error(msg); case None => true }
-
- private def largeUnzip() =
- testUnzip[ScalaObject] orElse
- testUnzip[scala.tools.nsc.Global]
- private def testUnzip[T](implicit mf: scala.reflect.Manifest[T]) =
- unzipFile(FileUtilities.classLocationFile(mf.erasure))
- private def unzipFile(jar: File) =
- FileUtilities.withTemporaryDirectory(log) { tmp =>
- FileUtilities.unzip(jar, Path.fromFile(tmp), log).left.toOption
- }
-
- // make the test independent of underlying platform and allow any unicode character in Strings to be encoded
- val charset = java.nio.charset.Charset.forName("UTF-8")
-
- import FileUtilities._
- private def writeAndCheckString(s: String) =
- {
- val result = withTemporaryFile( file => writeThen(file, s)( readString(file, charset, log) ) )
- handleResult[String](result, _ == s)
- }
- private def writeAndCheckBytes(b: Array[Byte]) =
- {
- val result = withTemporaryFile( file => writeThen(file, b)( readBytes(file, log) ) )
- handleResult[Array[Byte]](result, _ deepEquals b)
- }
- private def overwriteAndCheckStrings(a: String, b: String) =
- {
- val result = withTemporaryFile( file => writeThen(file, a)( writeThen(file, b)( readString(file, charset, log) ) ) )
- handleResult[String](result, _ == b)
- }
- private def overwriteAndCheckBytes(a: Array[Byte], b: Array[Byte]) =
- {
- val result = withTemporaryFile( file => writeThen(file, a)( writeThen(file, b)( readBytes(file, log) ) ) )
- handleResult[Array[Byte]](result, _ deepEquals b)
- }
- private def appendAndCheckStrings(a: String, b: String) =
- {
- val result = withTemporaryFile( file => appendThen(file, a)( appendThen(file, b)( readString(file, charset, log) ) ) )
- handleResult[String](result, _ == (a+b))
- }
- private def appendAndCheckBytes(a: Array[Byte], b: Array[Byte]) =
- {
- val result = withTemporaryFile( file => appendThen(file, a)( appendThen(file, b)( readBytes(file, log) ) ) )
- handleResult[Array[Byte]](result, _ deepEquals (a++b))
- }
-
- private def withTemporaryFile[T](f: File => Either[String, T]): Either[String, T] =
- doInTemporaryDirectory(log) { dir => f(new java.io.File(dir, "out")) }
-
- private def handleResult[T](result: Either[String, T], check: T => Boolean): Boolean =
- result match
- {
- case Left(err) => log.trace(new RuntimeException(err)); log.error(err); false
- case Right(x) => check(x)
- }
- private def writeThen[T](file: File, content: String)(action: => Either[String, T]) =
- write(file, content, charset, log).toLeft(()).right.flatMap { x =>action }
- private def writeThen[T](file: File, content: Array[Byte])(action: => Either[String, T]) =
- write(file, content, log).toLeft(()).right.flatMap { x =>action }
- private def appendThen[T](file: File, content: String)(action: => Either[String, T]) =
- append(file, content, charset, log).toLeft(()).right.flatMap { x =>action }
- private def appendThen[T](file: File, content: Array[Byte])(action: => Either[String, T]) =
- append(file, content, log).toLeft(()).right.flatMap { x =>action }
-}
View
182 sbt/src/test/scala/sbt/ReflectSpecification.scala
@@ -1,182 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008 Mark Harrah
- */
-package sbt
-
-// Still TODO:
-// inheritance- hierarchy, overriding
-
-import org.scalacheck._
-import scala.reflect.Manifest
-
-// specify members
-// specify classes
-// map members to classes
-// compile, instantiate base
-// get all vals
-// validate vals
-
-object ReflectiveSpecification extends Properties("ReflectUtilities")
-{
- import ReflectiveArbitrary._
- // pick other modifiers, any name, any type for the member, any type to find,
- // pick a class hierarchy, select any class from that hierarchy, add member
- // instantiate instance, perform reflection and verify it is empty
- specify("Public found", publicFound _)
- specify("Private hidden", privateHidden _)
-
- private def publicFound(isFinal: Boolean, decl: DeclarationType, name: Identifier, rType: ReturnType,
- findType: ReturnType, container: ConcreteContainer) =
- {
- val modifiers: Set[Modifier] = if(isFinal) Set(Final) else Set()
- val member = Member(Public, modifiers, decl, name.toString, rType, true)
- val shouldFind = decl != Def && rType.manifest <:< findType.manifest
- allVals(Map(container -> List(member)), container, findType.manifest).isEmpty == !shouldFind
- }
- private def privateHidden(isFinal: Boolean, decl: DeclarationType, name: Identifier, rType: ReturnType,
- findType: ReturnType, container: ConcreteContainer) =
- {
- val scope = Private(None)
- val modifiers: Set[Modifier] = if(isFinal) Set(Final) else Set()
- val member = Member(scope, modifiers, decl, name.toString, rType, true)
- allVals(Map(container -> List(member)), container, findType.manifest).isEmpty
- }
- private def allVals(classes: Map[Container, List[Member]], check: Container, manifest: Manifest[_]) =
- {
- val instance = ReflectiveCreate.compileInstantiate(classes, check)
- ReflectUtilities.allVals(instance)(manifest)
- }
-}
-
-object ReflectiveArbitrary
-{
- implicit val arbIdentifier: Arbitrary[Identifier] = Arbitrary { for(id <- Gen.identifier) yield Identifier(id) }
- implicit val arbDeclarationType: Arbitrary[DeclarationType] = Arbitrary { Gen.elements(Val, Def, LazyVal) }
- implicit val arbModifier: Arbitrary[Modifier] = Arbitrary { Gen.elements(Final, Abstract, Override) }
- // TODO: parameterize
- implicit val arbType: Arbitrary[ReturnType] =
- Arbitrary { Gen.elements(classes: _*) }
- implicit val arbConcrete: Arbitrary[ConcreteContainer] = Arbitrary(genConcrete)
- //implicit val arbContainer: Arbitrary[Container] = Arbitrary { Gen.oneOf(arbConcreteContainer, arbTrait) }
- //implicit val arbTrait: Arbitrary[Trait] = Arbitrary { }
-
- //TODO: inheritance
- def genConcrete = for(name <- Gen.identifier) yield ConcreteClass(name, None, Nil)
-
- val classes = List[ReturnType](
- typ[String]("String", "null"),
- typ[Object]("Object", "null"),
- typ[Int]("Int", "0"),
- typ[List[String]]("List[String]", "Nil"),
- typ[Option[Int]]("Option[Int]", "None") )
-
- def typ[T](name: String, defaultValue: String)(implicit mf: Manifest[T]) =
- BasicReturnType(name, Nil, mf, defaultValue)
-}
-
-object ReflectiveCreate
-{
- import scala.collection.mutable
-
- def compileInstantiate(classes: Map[Container, List[Member]], instantiate: Container): AnyRef =
- {
- val log = new ConsoleLogger
- log.setLevel(Level.Warn)
- val code = new StringBuilder
- def addMember(m: Member)
- {
- code.append(m.toString)
- code.append("\n")
- }
- def addClass(c: Container, m: List[Member])
- {
- code.append(c.signature)
- code.append(" {\n")
- m.foreach(addMember)
- code.append(" }\n")
- }
- for((c, members) <- classes) addClass(c, members)
-
- val codeString = code.toString
- def doCompileInstantiate(dir: java.io.File): Either[String, AnyRef] =
- {
- val basePath = new ProjectDirectory(dir)
- val source = basePath / "a.scala"
- val sourceFile = source.asFile
- val outputDirectory = basePath / "target"
- for(writeOK <- FileUtilities.write(sourceFile, codeString, log).toLeft("").right;
- compileOK <- Left("").right)//(new RawCompile(100))("reflect", source :: Nil, "", outputDirectory, Nil, log).toLeft("").right)
- yield
- {
- error("Reintegrate")
- val loader = new java.net.URLClassLoader(Array(outputDirectory.asURL), getClass.getClassLoader)
- val c = Class.forName(instantiate.name, true, loader)
- c.newInstance.asInstanceOf[AnyRef]
- }
- }
- FileUtilities.doInTemporaryDirectory(log)(doCompileInstantiate) match
- {
- case Left(err) => log.error(err); log.error(codeString); throw new RuntimeException(err)
- case Right(x) => x
- }
- }
-}
-
-final case class Identifier(override val toString: String) extends NotNull
-
-sealed abstract class Modifier(override val toString: String) extends NotNull
-object Final extends Modifier("final")
-object Abstract extends Modifier("abstract")
-object Override extends Modifier("override")
-
-sealed trait Scope extends NotNull
-sealed abstract class QualifiedScope(label: String, qualifier: Option[String]) extends Scope
-{
- override def toString = label + qualifier.map("[" + _ + "]").getOrElse("")
-}
-final case class Private(qualifier: Option[String]) extends QualifiedScope("private", qualifier)
-final case class Protected(qualifier: Option[String]) extends QualifiedScope("protected", qualifier)
-final object Public extends Scope { override def toString = "" }
-
-
-sealed abstract class DeclarationType(override val toString: String) extends NotNull
-object LazyVal extends DeclarationType("lazy val")
-object Val extends DeclarationType("val")
-object Def extends DeclarationType("def")
-
-sealed abstract class Container(prefix: String) extends NotNull
-{
- def signature: String = prefix + " " + name + parents.map(_.name).mkString(" extends ", " with ", "")
- def name: String
- def mixins: List[Trait]
- def parents: List[Container] = mixins
-}
-sealed abstract class ClassContainer(prefix: String) extends Container(prefix)
-{
- def base: Option[ClassContainer]
- override def parents = base.toList ::: mixins
-}
-sealed abstract class ConcreteContainer(prefix: String) extends ClassContainer(prefix)
-final case class AbstractClass(name: String, base: Option[ClassContainer], mixins: List[Trait]) extends ClassContainer("abstract class")
-final case class ConcreteClass(name: String, base: Option[ClassContainer], mixins: List[Trait]) extends ConcreteContainer("class")
-final case class Module(name: String, base: Option[ClassContainer], mixins: List[Trait]) extends ConcreteContainer("object")
-final case class Trait(name: String, mixins: List[Trait]) extends Container("trait")
-
-trait ReturnType
-{
- def name: String
- def parameters: List[ReturnType]
- def manifest: Manifest[_]
- def defaultValue: String
- override def toString = name
-}
-sealed case class BasicReturnType(name: String, parameters: List[ReturnType],
- manifest: Manifest[_], defaultValue: String) extends ReturnType
-
-case class Member(scope: Scope, modifiers: Set[Modifier], declaration: DeclarationType,
- name: String, mType: ReturnType, valueSpecified: Boolean) extends NotNull
-{
- override def toString = scope.toString + modifiers.mkString(" ", " "," ") +
- declaration.toString + " " + name + " : " + mType.toString +
- (if(valueSpecified) " = " + mType.defaultValue else "")
-}
View
3  testing/NOTICE
@@ -0,0 +1,3 @@
+Simple Build Tool: Testing Component
+Copyright 2008, 2009, 2010 Steven Blundy, Mark Harrah, Josh Cough
+Licensed under BSD-style license (see LICENSE)
View
22 sbt/src/main/scala/sbt/TestFramework.scala → testing/TestFramework.scala
@@ -6,7 +6,7 @@ package sbt
import java.net.URLClassLoader
import org.scalatools.testing.{AnnotatedFingerprint, Fingerprint, SubclassFingerprint, TestFingerprint}
import org.scalatools.testing.{Event, EventHandler, Framework, Runner, Runner2, Logger=>TLogger}
- import xsbt.ScalaInstance
+ import classpath.{ClasspathUtilities, DualLoader, FilteredLoader}
object Result extends Enumeration
{
@@ -44,7 +44,7 @@ final class TestDefinition(val name: String, val fingerprint: Fingerprint) exten
}
}
-final class TestRunner(framework: Framework, loader: ClassLoader, listeners: Seq[TestReportListener], log: Logger) extends NotNull
+final class TestRunner(framework: Framework, loader: ClassLoader, listeners: Seq[TestReportListener], log: Logger)
{
private[this] val delegate = framework.testRunner(loader, listeners.flatMap(_.contentLogger).toArray)
private[this] def run(testDefinition: TestDefinition, handler: EventHandler, args: Array[String]): Unit =
@@ -89,7 +89,7 @@ final class TestRunner(framework: Framework, loader: ClassLoader, listeners: Seq
TestFramework.safeForeach(listeners, log)(call)
}
-final class NamedTestTask(val name: String, action: => Option[String]) extends NotNull { def run() = action }
+final class NamedTestTask(val name: String, action: => Unit) { def run() = action }
object TestFramework
{
@@ -107,7 +107,7 @@ object TestFramework
private val TestFinishName = "test-finish"
private[sbt] def safeForeach[T](it: Iterable[T], log: Logger)(f: T => Unit): Unit =
- it.foreach(i => Control.trapAndLog(log){ f(i) } )
+ it.foreach(i => try f(i) catch { case e: Exception => log.trace(e); log.error(e.toString) })
def matches(a: Fingerprint, b: Fingerprint) =
(a, b) match
@@ -126,8 +126,8 @@ object TestFramework
log: Logger,
listeners: Seq[TestReportListener],
endErrorsEnabled: Boolean,
- setup: Iterable[() => Option[String]],
- cleanup: Iterable[() => Option[String]],
+ setup: Iterable[() => Unit],
+ cleanup: Iterable[() => Unit],
testArgsByFramework: Map[TestFramework, Seq[String]]):
(Iterable[NamedTestTask], Iterable[NamedTestTask], Iterable[NamedTestTask]) =
{
@@ -135,7 +135,7 @@ object TestFramework
val arguments = immutable.Map() ++
( for(framework <- frameworks; created <- framework.create(loader, log)) yield
(created, testArgsByFramework.getOrElse(framework, Nil)) )
- val cleanTmp = () => FileUtilities.clean(tempDir, log)
+ val cleanTmp = () => IO.delete(tempDir)
val mappedTests = testMap(arguments.keys.toList, tests, arguments)
if(mappedTests.isEmpty)
@@ -162,12 +162,12 @@ object TestFramework
assignTests()
(immutable.Map() ++ map) transform { (framework, tests) => (tests, args(framework)) }
}
- private def createTasks(work: Iterable[() => Option[String]], baseName: String) =
+ private def createTasks(work: Iterable[() => Unit], baseName: String) =
work.toList.zipWithIndex.map{ case (work, index) => new NamedTestTask(baseName + " " + (index+1), work()) }
private def createTestTasks(loader: ClassLoader, tests: Map[Framework, (Set[TestDefinition], Seq[String])], log: Logger,
- listeners: Seq[TestReportListener], endErrorsEnabled: Boolean, setup: Iterable[() => Option[String]],
- cleanup: Iterable[() => Option[String]]) =
+ listeners: Seq[TestReportListener], endErrorsEnabled: Boolean, setup: Iterable[() => Unit],
+ cleanup: Iterable[() => Unit]) =
{
val testsListeners = listeners.filter(_.isInstanceOf[TestsListener]).map(_.asInstanceOf[TestsListener])
def foreachListenerSafe(f: TestsListener => Unit): Unit = safeForeach(testsListeners, log)(f)
@@ -228,7 +228,7 @@ object TestFramework
val filterCompilerLoader = new FilteredLoader(scalaInstance.loader, ScalaCompilerJarPackages)
val interfaceFilter = (name: String) => name.startsWith("org.scalatools.testing.")
val notInterfaceFilter = (name: String) => !interfaceFilter(name)
- val dual = new xsbt.DualLoader(filterCompilerLoader, notInterfaceFilter, x => true, getClass.getClassLoader, interfaceFilter, x => false)
+ val dual = new DualLoader(filterCompilerLoader, notInterfaceFilter, x => true, getClass.getClassLoader, interfaceFilter, x => false)
ClasspathUtilities.makeLoader(classpath, dual, scalaInstance)
}
}
View
0  ...c/main/scala/sbt/TestReportListener.scala → testing/TestReportListener.scala
File renamed without changes
View
0  sbt/src/main/scala/sbt/impl/TestParser.scala → testing/impl/TestParser.scala
File renamed without changes
View
0  ...n/scala/sbt/impl/TestStatusReporter.scala → testing/impl/TestStatusReporter.scala
File renamed without changes
View
3  util/classpath/ClassLoaders.scala
@@ -1,7 +1,8 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009 Mark Harrah
*/
-package xsbt
+package sbt
+package classpath
import java.io.File
import java.net.{URI, URL, URLClassLoader}
View
67 ...c/main/scala/sbt/ClasspathUtilities.scala → util/classpath/ClasspathUtilities.scala
@@ -2,14 +2,14 @@
* Copyright 2008, 2009, 2010 Mark Harrah
*/
package sbt
+package classpath
import java.io.File
import java.net.{URI, URL, URLClassLoader}
import java.util.Collections
import scala.collection.Set
-import scala.collection.mutable.{HashSet, ListBuffer}
-import xsbt.ScalaInstance
-import xsbt.FileUtilities.{createTemporaryDirectory, withTemporaryDirectory, write}
+import scala.collection.mutable.{HashSet, LinkedHashSet, ListBuffer}
+import IO.{createTemporaryDirectory, write}
object ClasspathUtilities
{
@@ -57,7 +57,7 @@ object ClasspathUtilities
}
private[sbt] def printSource(c: Class[_]) =
- println(c.getName + " loader=" +c.getClassLoader + " location=" + FileUtilities.classLocationFile(c))
+ println(c.getName + " loader=" +c.getClassLoader + " location=" + IO.classLocationFile(c))
def isArchive(path: Path): Boolean = isArchive(path.asFile)
def isArchive(file: File): Boolean = isArchiveName(file.getName)
@@ -66,16 +66,16 @@ object ClasspathUtilities
private[sbt] def separate(paths: Iterable[File]): (Iterable[File], Iterable[File]) = paths.partition(isArchive)
// Partitions the given classpath into (jars, directories)
private[sbt] def separatePaths(paths: Iterable[Path]) = separate(paths.map(_.asFile.getCanonicalFile))
- private[sbt] def buildSearchPaths(classpath: Iterable[Path]): (wrap.Set[File], wrap.Set[File]) =
+ private[sbt] def buildSearchPaths(classpath: Iterable[Path]): (collection.Set[File], collection.Set[File]) =
{
val (jars, dirs) = separatePaths(classpath)
(linkedSet(jars ++ extraJars.toList), linkedSet(dirs ++ extraDirs.toList))
}
- private[sbt] def onClasspath(classpathJars: wrap.Set[File], classpathDirectories: wrap.Set[File], file: File): Boolean =
+ private[sbt] def onClasspath(classpathJars: collection.Set[File], classpathDirectories: collection.Set[File], file: File): Boolean =
{
val f = file.getCanonicalFile
if(ClasspathUtilities.isArchive(f))
- classpathJars.contains(f)
+ classpathJars(f)
else
classpathDirectories.toList.find(Path.relativize(_, f).isDefined).isDefined
}
@@ -83,8 +83,9 @@ object ClasspathUtilities
/** Returns all entries in 'classpath' that correspond to a compiler plugin.*/
private[sbt] def compilerPlugins(classpath: Iterable[Path]): Iterable[File] =
{
+ import collection.JavaConversions._
val loader = new URLClassLoader(Path.getURLs(classpath))
- wrap.Wrappers.toList(loader.getResources("scalac-plugin.xml")).flatMap(asFile(true))
+ loader.getResources("scalac-plugin.xml").toList.flatMap(asFile(true))
}
/** Converts the given URL to a File. If the URL is for an entry in a jar, the File for the jar is returned. */
private[sbt] def asFile(url: URL): List[File] = asFile(false)(url)
@@ -94,7 +95,7 @@ object ClasspathUtilities
{
url.getProtocol match
{
- case "file" if !jarOnly=> FileUtilities.toFile(url) :: Nil
+ case "file" if !jarOnly=> IO.toFile(url) :: Nil
case "jar" =>
val path = url.getPath
val end = path.indexOf('!')
@@ -109,7 +110,7 @@ object ClasspathUtilities
{
import scala.tools.nsc.GenericRunnerCommand
val settings = (new GenericRunnerCommand(Nil, message => error(message))).settings
- val bootPaths = FileUtilities.pathSplit(settings.bootclasspath.value).map(p => new File(p)).toList
+ val bootPaths = IO.pathSplit(settings.bootclasspath.value).map(p => new File(p)).toList
val (bootJars, bootDirs) = separate(bootPaths)
val extJars =
{
@@ -120,41 +121,21 @@ object ClasspathUtilities
for(dir <- dir.listFiles(DirectoryFilter))
findJars(dir)
}
- for(path <- FileUtilities.pathSplit(settings.extdirs.value); val dir = new File(path) if dir.isDirectory)
+ for(path <- IO.pathSplit(settings.extdirs.value); val dir = new File(path) if dir.isDirectory)
findJars(dir)
buffer.readOnly.map(_.getCanonicalFile)
}
(linkedSet(extJars ++ bootJars), linkedSet(bootDirs))
}
- private def linkedSet[T](s: Iterable[T]): wrap.Set[T] =
+ private def linkedSet[T](s: Iterable[T]): Set[T] =
{
- val set = new wrap.MutableSetWrapper(new java.util.LinkedHashSet[T])
+ val set = new LinkedHashSet[T]
set ++= s
- set.readOnly
+ set
}
}
-private abstract class LoaderBase(urls: Array[URL], parent: ClassLoader) extends URLClassLoader(urls, parent) with NotNull
-{
- require(parent != null) // included because a null parent is legitimate in Java
- @throws(classOf[ClassNotFoundException])
- override final def loadClass(className: String, resolve: Boolean): Class[_] =
- {
- val loaded = findLoadedClass(className)
- val found =
- if(loaded == null)
- doLoadClass(className)
- else
- loaded
-
- if(resolve)
- resolveClass(found)
- found
- }
- protected def doLoadClass(className: String): Class[_]
- protected final def selfLoadClass(className: String): Class[_] = super.loadClass(className, false)
-}
-private class IntermediateLoader(urls: Array[URL], parent: ClassLoader) extends LoaderBase(urls, parent) with NotNull
+private class IntermediateLoader(urls: Array[URL], parent: ClassLoader) extends LoaderBase(urls, parent)
{
def doLoadClass(className: String): Class[_] =
{
@@ -163,12 +144,12 @@ private class IntermediateLoader(urls: Array[URL], parent: ClassLoader) extends
if(className.startsWith(Loaders.SbtPackage))
findClass(className)
else
- selfLoadClass(className)
+ defaultLoadClass(className)
}
}
/** Delegates class loading to `parent` for all classes included by `filter`. An attempt to load classes excluded by `filter`
* results in a `ClassNotFoundException`.*/
-private class FilteredLoader(parent: ClassLoader, filter: ClassFilter) extends ClassLoader(parent) with NotNull
+class FilteredLoader(parent: ClassLoader, filter: ClassFilter) extends ClassLoader(parent)
{
require(parent != null) // included because a null parent is legitimate in Java
def this(parent: ClassLoader, excludePackages: Iterable[String]) = this(parent, new ExcludePackagesFilter(excludePackages))
@@ -182,7 +163,7 @@ private class FilteredLoader(parent: ClassLoader, filter: ClassFilter) extends C
throw new ClassNotFoundException(className)
}
}
-private class SelectiveLoader(urls: Array[URL], parent: ClassLoader, filter: ClassFilter) extends URLClassLoader(urls, parent) with NotNull
+private class SelectiveLoader(urls: Array[URL], parent: ClassLoader, filter: ClassFilter) extends URLClassLoader(urls, parent)
{
require(parent != null) // included because a null parent is legitimate in Java
def this(urls: Array[URL], parent: ClassLoader, includePackages: Iterable[String]) = this(urls, parent, new IncludePackagesFilter(includePackages))
@@ -201,26 +182,26 @@ private class SelectiveLoader(urls: Array[URL], parent: ClassLoader, filter: Cla
}
}
}
-private trait ClassFilter
+trait ClassFilter
{
def include(className: String): Boolean
}
-private abstract class PackageFilter(packages: Iterable[String]) extends ClassFilter
+abstract class PackageFilter(packages: Iterable[String]) extends ClassFilter
{
require(packages.forall(_.endsWith(".")))
protected final def matches(className: String): Boolean = packages.exists(className.startsWith)
}
-private class ExcludePackagesFilter(exclude: Iterable[String]) extends PackageFilter(exclude)
+class ExcludePackagesFilter(exclude: Iterable[String]) extends PackageFilter(exclude)
{
def include(className: String): Boolean = !matches(className)
}
-private class IncludePackagesFilter(include: Iterable[String]) extends PackageFilter(include)
+class IncludePackagesFilter(include: Iterable[String]) extends PackageFilter(include)
{
def include(className: String): Boolean = matches(className)
}
private class LazyFrameworkLoader(runnerClassName: String, urls: Array[URL], parent: ClassLoader, grandparent: ClassLoader)
- extends LoaderBase(urls, parent) with NotNull
+ extends LoaderBase(urls, parent)
{
def doLoadClass(className: String): Class[_] =
{
View
3  util/classpath/DualLoader.scala
@@ -1,7 +1,8 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009 Mark Harrah
*/
-package xsbt
+package sbt
+package classpath
import java.net.URL
import java.util.Enumeration
View
0  sbt/src/main/scala/sbt/ModuleUtilities.scala → util/classpath/ModuleUtilities.scala
File renamed without changes
View
2  util/classpath/NOTICE
@@ -1,3 +1,3 @@
Simple Build Tool: Classpath Component
-Copyright 2008, 2009 Mark Harrah
+Copyright 2008, 2009, 2010 Mark Harrah, Stuart Roebuck
Licensed under BSD-style license (see LICENSE)
View
2  ...src/main/scala/sbt/ReflectUtilities.scala → util/classpath/ReflectUtilities.scala
@@ -1,7 +1,7 @@
/* sbt -- Simple Build Tool
* Copyright 2008 David MacIver, Mark Harrah
*/
-package sbt;
+package sbt
import scala.collection._
View
5 compile/ScalaInstance.scala → util/classpath/ScalaInstance.scala
@@ -1,4 +1,7 @@
-package xsbt
+/* sbt -- Simple Build Tool
+ * Copyright 2009, 2010 Mark Harrah
+ */
+package sbt
import java.io.File
View
3  util/complete/NOTICE
@@ -0,0 +1,3 @@
+Simple Build Tool: Completion Component
+Copyright 2010 Mark Harrah
+Licensed under BSD-style license (see LICENSE)
View
23 util/io/IO.scala
@@ -6,7 +6,7 @@ package sbt
import Using._
import ErrorHandling.translate
-import java.io.{ByteArrayOutputStream, BufferedWriter, File, FileInputStream, InputStream, OutputStream}
+import java.io.{BufferedReader, ByteArrayOutputStream, BufferedWriter, File, FileInputStream, InputStream, OutputStream}
import java.net.{URI, URISyntaxException, URL}
import java.nio.charset.Charset
import java.util.jar.{Attributes, JarEntry, JarFile, JarInputStream, JarOutputStream, Manifest}
@@ -395,10 +395,11 @@ object IO
}
def copyLastModified(sourceFile: File, targetFile: File) = targetFile.setLastModified( sourceFile.lastModified )
def defaultCharset = utf8
+
def write(file: File, content: String, charset: Charset = defaultCharset, append: Boolean = false): Unit =
- writeCharset(file, content, charset, append) { _.write(content) }
+ writer(file, content, charset, append) { _.write(content) }
- def writeCharset[T](file: File, content: String, charset: Charset, append: Boolean)(f: BufferedWriter => T): T =
+ def writer[T](file: File, content: String, charset: Charset, append: Boolean = false)(f: BufferedWriter => T): T =
{
if(charset.newEncoder.canEncode(content))
fileWriter(charset, append)(file) { f }
@@ -406,6 +407,9 @@ object IO
error("String cannot be encoded by charset " + charset.name)
}
+ def reader[T](file: File, charset: Charset = defaultCharset)(f: BufferedReader => T): T =
+ fileReader(charset)(file) { f }
+
def read(file: File, charset: Charset = defaultCharset): String =
{
val out = new ByteArrayOutputStream(file.length.toInt)
@@ -428,6 +432,17 @@ object IO
out.toByteArray
}
+ def append(file: File, content: String, charset: Charset = defaultCharset): Unit =
+ write(file, content, charset, true)
+ def append(file: File, bytes: Array[Byte]): Unit =
+ writeBytes(file, bytes, true)
+
+ def write(file: File, bytes: Array[Byte]): Unit =
+ writeBytes(file, bytes, false)
+ private def writeBytes(file: File, bytes: Array[Byte], append: Boolean): Unit =
+ fileOutputStream(append)(file) { _.write(bytes) }
+
+
// Not optimized for large files
def readLines(file: File, charset: Charset = defaultCharset): List[String] =
{
@@ -441,7 +456,7 @@ object IO
}
}
def writeLines(file: File, lines: Seq[String], charset: Charset = defaultCharset, append: Boolean = false): Unit =
- writeCharset(file, lines.headOption.getOrElse(""), charset, append) { w =>
+ writer(file, lines.headOption.getOrElse(""), charset, append) { w =>
lines.foreach { line => w.write(line); w.newLine() }
}
View
79 util/io/Pack.scala
@@ -0,0 +1,79 @@
+/* sbt -- Simple Build Tool
+ * Copyright 2009 Mark Harrah
+ */
+package sbt
+
+import java.io.{File, FileOutputStream}
+import java.util.jar.{JarEntry, JarFile, JarOutputStream, Pack200}
+import IO._
+
+object Pack
+{
+ def pack(jarPath: File, out: File): Unit = pack(jarPath, out, defaultPackerOptions)
+ def pack(jarPath: File, out: File, options: Iterable[(String, String)])
+ {
+ val packer = Pack200.newPacker
+ import collection.JavaConversions._
+ packer.properties ++= options
+
+ Using.jarFile(false)(jarPath) { f =>
+ Using.fileOutputStream()(out) { stream =>
+ packer.pack(f, stream)
+ }
+ }
+ }
+ def unpack(packedPath: File, toJarPath: File)
+ {
+ val unpacker = Pack200.newUnpacker
+ Using.fileOutputStream()(toJarPath) { fileStream =>
+ Using.jarOutputStream(fileStream) { jarOut =>
+ unpacker.unpack(packedPath, jarOut)
+ }
+ }
+ }
+ def defaultPackerOptions = scala.collection.immutable.Map()
+}
+
+import java.net.URL
+/** This is somewhat of a mess and is not entirely correct. jarsigner doesn't work properly
+* on scalaz and it is difficult to determine whether a jar is both signed and valid. */
+object SignJar
+{
+ final class SignOption private[SignJar](val toList: List[String], val signOnly: Boolean)
+ {
+ override def toString = toList.mkString(" ")
+ }
+ def keyStore(url: URL) = new SignOption("-keystore" :: url.toExternalForm :: Nil, true)
+ def signedJar(p: Path) = new SignOption("-signedjar" :: p.asFile.getAbsolutePath :: Nil, true)
+ def verbose = new SignOption("-verbose" :: Nil, false)
+ def sigFile(name: String) = new SignOption("-sigfile" :: name :: Nil, true)
+ def storeType(t: String) = new SignOption("-storetype" :: t :: Nil, false)
+ def provider(p: String) = new SignOption("-provider" :: p :: Nil, false)
+ def providerName(p: String) = new SignOption("-providerName" :: p :: Nil, false)
+ def storePassword(p: String) = new SignOption("-storepass" :: p :: Nil, true)
+ def keyPassword(p: String) = new SignOption("-keypass" :: p :: Nil, true)
+
+ private def VerifyOption = "-verify"
+
+ /** Uses jarsigner to sign the given jar. */
+ def sign(jarPath: File, alias: String, options: Seq[SignOption])(fork: (String, List[String]) => Int)
+ {
+ require(!alias.trim.isEmpty, "Alias cannot be empty")
+ val arguments = options.toList.flatMap(_.toList) ::: jarPath.getAbsolutePath :: alias :: Nil
+ execute("signing", arguments)(fork)
+ }
+ /** Uses jarsigner to verify the given jar.*/
+ def verify(jarPath: File, options: Seq[SignOption])(fork: (String, List[String]) => Int)
+ {
+ val arguments = options.filter(!_.signOnly).toList.flatMap(_.toList) ::: VerifyOption :: jarPath.getAbsolutePath :: Nil
+ execute("verifying", arguments)(fork)
+ }
+ private def execute(action: String, arguments: List[String])(fork: (String, List[String]) => Int)
+ {
+ val exitCode = fork(CommandName, arguments)
+ if(exitCode != 0)
+ error("Error " + action + " jar (exit code was " + exitCode + ".)")
+ }
+
+ private val CommandName = "jarsigner"
+}
View
3  util/io/Path.scala
@@ -246,7 +246,8 @@ object Path extends Alternatives with Mapper
}
def fromFile(file: String): Path = fromFile(new File(file))
def fromFile(file: File): Path = new FilePath(file)
- def fromFiles(files: Traversable[File]): Traversable[Path] = files.map(fromFile)
+ import collection.generic.{CanBuildFrom, FilterMonadic}
+ def fromFiles[Repr, That](files: FilterMonadic[File, Repr])(implicit bf: CanBuildFrom[Repr, Path, That]): That = files.map(fromFile)
def getFiles(files: Traversable[Path]): immutable.Set[File] = files.map(_.asFile).toSet
def getURLs(files: Traversable[Path]): Array[URL] = files.map(_.asURL).toArray
View
37 util/io/SourceModificationWatch.scala
@@ -0,0 +1,37 @@
+/* sbt -- Simple Build Tool
+ * Copyright 2009, 2010 Mikko Peltonen, Stuart Roebuck, Mark Harrah
+ */
+package sbt
+
+object SourceModificationWatch
+{
+ def watchUntil(sourcesFinder: PathFinder, pollDelaySec: Int)(terminationCondition: => Boolean)(onSourcesModified: => Unit)
+ {
+ def sourceFiles: Iterable[java.io.File] = sourcesFinder.getFiles
+ def loop(lastCallbackCallTime: Long, previousFileCount: Int, awaitingQuietPeriod:Boolean)
+ {
+ val (lastModifiedTime, fileCount) =
+ ( (0L, 0) /: sourceFiles) {(acc, file) => (math.max(acc._1, file.lastModified), acc._2 + 1)}
+
+ val sourcesModified =
+ lastModifiedTime > lastCallbackCallTime ||
+ previousFileCount != fileCount
+
+ val newCallbackCallTime =
+ if (sourcesModified && !awaitingQuietPeriod)
+ System.currentTimeMillis
+ else if (!sourcesModified && awaitingQuietPeriod)
+ {
+ onSourcesModified
+ lastCallbackCallTime
+ }
+ else
+ lastCallbackCallTime
+
+ Thread.sleep(pollDelaySec * 1000)
+ if(!terminationCondition)
+ loop(newCallbackCallTime, fileCount, sourcesModified)
+ }
+ loop(0L, 0, false)
+ }
+}
View
78 util/io/src/test/scala/FileUtilitiesSpecification.scala
@@ -0,0 +1,78 @@
+/* sbt -- Simple Build Tool
+ * Copyright 2008, 2009 Mark Harrah
+ */
+package sbt
+
+import org.scalacheck._
+import Prop._
+import Arbitrary.{arbString => _, arbChar => _, _}
+import java.io.{File, IOException}
+
+object WriteContentSpecification extends Properties("Write content")
+{
+ property("Roundtrip string") = forAll( writeAndCheckString _)
+ property("Roundtrip bytes") = forAll(writeAndCheckBytes _)
+ property("Write string overwrites") = forAll(overwriteAndCheckStrings _)
+ property("Write bytes overwrites") = forAll( overwriteAndCheckBytes _)
+ property("Append string appends") = forAll( appendAndCheckStrings _)
+ property("Append bytes appends") = forAll( appendAndCheckBytes _)
+ property("Unzip doesn't stack overflow") = largeUnzip()
+
+ implicit lazy val validChar: Arbitrary[Char] = Arbitrary( for(i <- Gen.choose(0, 0xd7ff)) yield i.toChar )
+ implicit lazy val validString: Arbitrary[String] = Arbitrary(arbitrary[List[Char]] map (_.mkString))
+
+ private def largeUnzip() =
+ {
+ testUnzip[ScalaObject]
+ testUnzip[scala.tools.nsc.Global]
+ true
+ }
+ private def testUnzip[T](implicit mf: scala.reflect.Manifest[T]) =
+ unzipFile(IO.classLocationFile(mf.erasure))
+ private def unzipFile(jar: File) =
+ IO.withTemporaryDirectory { tmp =>
+ IO.unzip(jar, tmp)
+ }
+
+ // make the test independent of underlying platform and allow any unicode character in Strings to be encoded
+ val charset = java.nio.charset.Charset.forName("UTF-8")
+
+ import IO._
+ private def writeAndCheckString(s: String) =
+ withTemporaryFile { file =>
+ write(file, s, charset)
+ read(file, charset) == s
+ }
+ private def writeAndCheckBytes(b: Array[Byte]) =
+ withTemporaryFile { file =>
+ write(file, b)
+ readBytes(file) sameElements b
+ }
+ private def overwriteAndCheckStrings(a: String, b: String) =
+ withTemporaryFile { file =>
+ write(file, a, charset)
+ write(file, b, charset)
+ read(file, charset) == b
+ }
+ private def overwriteAndCheckBytes(a: Array[Byte], b: Array[Byte]) =
+ withTemporaryFile { file =>
+ write(file, a)
+ write(file, b)
+ readBytes(file) sameElements b
+ }
+ private def appendAndCheckStrings(a: String, b: String) =
+ withTemporaryFile { file =>
+ append(file, a, charset)
+ append(file, b, charset)
+ read(file, charset) == (a+b)
+ }
+ private def appendAndCheckBytes(a: Array[Byte], b: Array[Byte]) =
+ withTemporaryFile { file =>
+ append(file, a)
+ append(file, b)
+ readBytes(file) sameElements (a++b)
+ }
+
+ private def withTemporaryFile[T](f: File => T): T =
+ withTemporaryDirectory { dir => f(new java.io.File(dir, "out")) }
+}
View
6 util/log/BufferedLogger.scala
@@ -1,7 +1,7 @@
/* sbt -- Simple Build Tool
* Copyright 2008, 2009, 2010 Mark Harrah
*/
- package xsbt
+package sbt
import sbt.{AbstractLogger, ControlEvent, Level, Log, LogEvent, SetLevel, SetTrace, Success, Trace}
import scala.collection.mutable.ListBuffer
@@ -50,14 +50,14 @@ class BufferedLogger(delegate: AbstractLogger) extends AbstractLogger
def setLevel(newLevel: Level.Value)
{
- buffer += new SetLevel(newLevel)
+ buffer += new SetLevel(newLevel)
delegate.setLevel(newLevel)
}
def getLevel = delegate.getLevel
def getTrace = delegate.getTrace
def setTrace(level: Int)
{
- buffer += new SetTrace(level)
+ buffer += new SetTrace(level)
delegate.setTrace(level)
}
View
24 util/log/FullLogger.scala
@@ -0,0 +1,24 @@
+/* sbt -- Simple Build Tool
+ * Copyright 2010 Mark Harrah
+ */
+package sbt
+
+/** Promotes the simple Logger interface to the full AbstractLogger interface. */
+class FullLogger(delegate: Logger, override val ansiCodesSupported: Boolean = false) extends BasicLogger
+{
+ def trace(t: => Throwable)
+ {
+ if(traceEnabled)
+ delegate.trace(t)
+ }
+ def log(level: Level.Value, message: => String)
+ {
+ if(atLevel(level))
+ delegate.log(level, message)
+ }
+ def success(message: => String): Unit =
+ info(message)
+ def control(event: ControlEvent.Value, message: => String): Unit =
+ info(message)
+ def logAll(events: Seq[LogEvent]): Unit = events.foreach(log)
+}
View
30 util/log/Logger.scala
@@ -1,28 +1,20 @@
/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah
+ * Copyright 2008, 2009, 2010 Mark Harrah
*/
package sbt
import xsbti.{Logger => xLogger, F0}
-abstract class AbstractLogger extends xLogger with NotNull
+abstract class AbstractLogger extends Logger
{
def getLevel: Level.Value
def setLevel(newLevel: Level.Value)
def setTrace(flag: Int)
def getTrace: Int
final def traceEnabled = getTrace >= 0
- def ansiCodesSupported = false
def atLevel(level: Level.Value) = level.id >= getLevel.id
- def trace(t: => Throwable): Unit
- final def verbose(message: => String): Unit = debug(message)
- final def debug(message: => String): Unit = log(Level.Debug, message)
- final def info(message: => String): Unit = log(Level.Info, message)
- final def warn(message: => String): Unit = log(Level.Warn, message)
- final def error(message: => String): Unit = log(Level.Error, message)
def success(message: => String): Unit
- def log(level: Level.Value, message: => String): Unit
def control(event: ControlEvent.Value, message: => String): Unit
def logAll(events: Seq[LogEvent]): Unit
@@ -39,11 +31,27 @@ abstract class AbstractLogger extends xLogger with NotNull
case c: ControlEvent => control(c.event, c.msg)
}
}
+}
+
+/** This is intended to be the simplest logging interface for use by code that wants to log.
+* It does not include configuring the logger. */
+trait Logger extends xLogger
+{
+ final def verbose(message: => String): Unit = debug(message)
+ final def debug(message: => String): Unit = log(Level.Debug, message)
+ final def info(message: => String): Unit = log(Level.Info, message)
+ final def warn(message: => String): Unit = log(Level.Warn, message)
+ final def error(message: => String): Unit = log(Level.Error, message)
+ def ansiCodesSupported = false
+
+ def trace(t: => Throwable): Unit
+ def log(level: Level.Value, message: => String): Unit
+
def debug(msg: F0[String]): Unit = log(Level.Debug, msg)
def warn(msg: F0[String]): Unit = log(Level.Warn, msg)
def info(msg: F0[String]): Unit = log(Level.Info, msg)
def error(msg: F0[String]): Unit = log(Level.Error, msg)
def trace(msg: F0[Throwable]) = trace(msg.apply)
def log(level: Level.Value, msg: F0[String]): Unit = log(level, msg.apply)
-}
+}
View
4 util/log/LoggerWriter.scala
@@ -5,9 +5,9 @@ package sbt
/** Provides a `java.io.Writer` interface to a `Logger`. Content is line-buffered and logged at `level`.
* A line is delimited by `nl`, which is by default the platform line separator.*/
-class LoggerWriter(delegate: AbstractLogger, level: Level.Value, nl: String) extends java.io.Writer
+class LoggerWriter(delegate: Logger, level: Level.Value, nl: String) extends java.io.Writer
{
- def this(delegate: AbstractLogger, level: Level.Value) = this(delegate, level, System.getProperty("line.separator"))
+ def this(delegate: Logger, level: Level.Value) = this(delegate, level, System.getProperty("line.separator"))
private[this] val buffer = new StringBuilder
View
2  sbt/src/main/scala/sbt/Process.scala → util/process/Process.scala
@@ -14,8 +14,6 @@ object Process
implicit def apply(command: String): ProcessBuilder = apply(command, None)
implicit def apply(command: Seq[String]): ProcessBuilder = apply (command.toArray, None)
def apply(command: String, arguments: Seq[String]): ProcessBuilder = apply(command :: arguments.toList, None)
- /** create ProcessBuilder with working dir set to path and extra environment variables */
- def apply(command: String, cwd: Path, extraEnv: (String,String)*): ProcessBuilder = apply(command, cwd.asFile, extraEnv : _*)
/** create ProcessBuilder with working dir set to File and extra environment variables */
def apply(command: String, cwd: File, extraEnv: (String,String)*): ProcessBuilder =
apply(command, Some(cwd), extraEnv : _*)
View
8 ...src/main/scala/sbt/impl/ProcessImpl.scala → util/process/ProcessImpl.scala
@@ -41,7 +41,7 @@ private object Future
}
}
-private object BasicIO
+object BasicIO
{
def apply(buffer: StringBuffer, log: Option[Logger], withIn: Boolean) = new ProcessIO(input(withIn), processFully(buffer), getErr(log))
def apply(log: Logger, withIn: Boolean) = new ProcessIO(input(withIn), processFully(log, Level.Info), processFully(log, Level.Error))
@@ -50,7 +50,7 @@ private object BasicIO
def ignoreOut = (i: OutputStream) => ()
final val BufferSize = 8192
- final val Newline = FileUtilities.Newline
+ final val Newline = System.getProperty("line.separator")
def close(c: java.io.Closeable) = try { c.close() } catch { case _: java.io.IOException => () }
def processFully(log: Logger, level: Level.Value): InputStream => Unit = processFully(line => log.log(level, line))
@@ -161,8 +161,8 @@ private abstract class AbstractProcessBuilder extends ProcessBuilder with SinkPa
def !<(log: Logger) = runBuffered(log, true)
private[this] def runBuffered(log: Logger, connectInput: Boolean) =
{
- val log2 = new BufferedLogger(log)
- log2.bufferAll { run(log2, connectInput).exitValue() }
+ val log2 = new BufferedLogger(new FullLogger(log))
+ log2.buffer { run(log2, connectInput).exitValue() }
}
def !(io: ProcessIO) = run(io).exitValue()
View
29 ...test/scala/sbt/ProcessSpecification.scala → ...src/test/scala/ProcessSpecification.scala
@@ -12,13 +12,13 @@ object ProcessSpecification extends Properties("Process I/O")
implicit val exitCodeArb: Arbitrary[Array[Byte]] = Arbitrary(Gen.choose(0, 10) flatMap { size => Gen.resize(size, Arbitrary.arbArray[Byte].arbitrary) })
- specify("Correct exit code", (exitCode: Byte) => checkExit(exitCode))
- specify("#&& correct", (exitCodes: Array[Byte]) => checkBinary(exitCodes)(_ #&& _)(_ && _))
- specify("#|| correct", (exitCodes: Array[Byte]) => checkBinary(exitCodes)(_ #|| _)(_ || _))
- specify("### correct", (exitCodes: Array[Byte]) => checkBinary(exitCodes)(_ ### _)( (x,latest) => latest))
- specify("Pipe to output file", (data: Array[Byte]) => checkFileOut(data))
- specify("Pipe to input file", (data: Array[Byte]) => checkFileIn(data))
- specify("Pipe to process", (data: Array[Byte]) => checkPipe(data))
+ /*property("Correct exit code") = forAll( (exitCode: Byte) => checkExit(exitCode))
+ property("#&& correct") = forAll( (exitCodes: Array[Byte]) => checkBinary(exitCodes)(_ #&& _)(_ && _))
+ property("#|| correct") = forAll( (exitCodes: Array[Byte]) => checkBinary(exitCodes)(_ #|| _)(_ || _))
+ property("### correct") = forAll( (exitCodes: Array[Byte]) => checkBinary(exitCodes)(_ ### _)( (x,latest) => latest))*/
+ property("Pipe to output file") = forAll( (data: Array[Byte]) => checkFileOut(data))
+ property("Pipe to input file") = forAll( (data: Array[Byte]) => checkFileIn(data))
+ property("Pipe to process") = forAll( (data: Array[Byte]) => checkPipe(data))
private def checkBinary(codes: Array[Byte])(reduceProcesses: (ProcessBuilder, ProcessBuilder) => ProcessBuilder)(reduceExit: (Boolean, Boolean) => Boolean) =
{
@@ -64,14 +64,13 @@ object ProcessSpecification extends Properties("Process I/O")
val temporaryFile2 = temp()
try
{
- FileUtilities.write(temporaryFile1, data, log)
+ IO.write(temporaryFile1, data)
val process = f(temporaryFile1, temporaryFile2)
( process ! ) == 0 &&
{
- val result =
- for(b1 <- FileUtilities.readBytes(temporaryFile1, log).right; b2 <- FileUtilities.readBytes(temporaryFile2, log).right) yield
- b1 deepEquals b2
- result.fold(error, x => x)
+ val b1 = IO.readBytes(temporaryFile1)
+ val b2 = IO.readBytes(temporaryFile2)
+ b1 sameElements b2
}
}
finally
@@ -85,10 +84,10 @@ object ProcessSpecification extends Properties("Process I/O")
{
val ignore = echo // just for the compile dependency so that this test is rerun when TestedProcess.scala changes, not used otherwise
- val thisClasspath = List(getSource[ScalaObject], getSource[sbt.Logger], getSource[sbt.SourceTag]).mkString(File.pathSeparator)
+ val thisClasspath = List(getSource[ScalaObject], getSource[IO.type], getSource[SourceTag]).mkString(File.pathSeparator)
"java -cp " + thisClasspath + " " + command
}
- private def getSource[T](implicit mf: scala.reflect.Manifest[T]): String =
- (FileUtilities.toFile(mf.erasure.getProtectionDomain.getCodeSource.getLocation)).getAbsolutePath
+ private def getSource[T : Manifest]: String =
+ IO.classLocationFile[T].getAbsolutePath
}
private trait SourceTag
View
25 sbt/src/test/scala/sbt/TestedProcess.scala → ...rocess/src/test/scala/TestedProcess.scala
@@ -1,6 +1,6 @@
package sbt
-import java.io.File
+import java.io.{File, FileNotFoundException, IOException}
object exit
{
@@ -13,18 +13,19 @@ object cat
{
def main(args: Array[String])
{
- val result =
+ try {
if(args.length == 0)
- FileUtilities.transfer(System.in, System.out, log)
+ IO.transfer(System.in, System.out)
else
catFiles(args.toList)
- result match
- {
- case Some(err) => System.err.println("Error: " + err); System.exit(1