From b408b441569dc165f4d41b048ff64253695a491d Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Wed, 9 Mar 2016 01:48:09 -0500 Subject: Add feature for starting the Scala REPL in arbitrary versions, propagate logger as implicits --- stage2/AdminStage2.scala | 9 +++++---- stage2/AdminTasks.scala | 23 ++++++++++++++++++++++- stage2/BuildBuild.scala | 2 +- stage2/Lib.scala | 26 ++++++++++---------------- stage2/PackageBuild.scala | 4 ++-- 5 files changed, 40 insertions(+), 24 deletions(-) (limited to 'stage2') diff --git a/stage2/AdminStage2.scala b/stage2/AdminStage2.scala index 4120b1c..59f8f7d 100644 --- a/stage2/AdminStage2.scala +++ b/stage2/AdminStage2.scala @@ -1,11 +1,12 @@ package cbt object AdminStage2{ - def main(args: Array[String]) = { - val init = new Init(args.drop(3)) + def main(_args: Array[String]) = { + val args = _args.drop(1).dropWhile(Seq("admin","direct") contains _) + val init = new Init(args) val lib = new Lib(init.logger) - val adminTasks = new AdminTasks(lib, args.drop(3)) + val adminTasks = new AdminTasks(lib, args) new lib.ReflectObject(adminTasks){ def usage: String = "Available methods: " ++ lib.taskNames(subclassType).mkString(" ") - }.callNullary(args.lift(2)) + }.callNullary(args.lift(0)) } } diff --git a/stage2/AdminTasks.scala b/stage2/AdminTasks.scala index 2f7efe1..70b140e 100644 --- a/stage2/AdminTasks.scala +++ b/stage2/AdminTasks.scala @@ -1,12 +1,33 @@ package cbt +import scala.collection.immutable.Seq class AdminTasks(lib: Lib, args: Array[String]){ + implicit val logger: Logger = lib.logger def resolve = { ClassPath.flatten( - args(0).split(",").toVector.map{ + args(1).split(",").toVector.map{ d => val v = d.split(":") new MavenDependency(v(0),v(1),v(2))(lib.logger).classpath } ) } + def amm = ammonite + def ammonite = { + val version = args.lift(1).getOrElse(constants.scalaVersion) + val scalac = new ScalaCompilerDependency( version ) + val d = MavenDependency( + "com.lihaoyi","ammonite-repl_2.11.7",args.lift(1).getOrElse("0.5.6") + ) + // FIXME: this does not work quite yet, throws NoSuchFileException: /ammonite/repl/frontend/ReplBridge$.class + lib.runMain( + "ammonite.repl.Main", Seq(), d.classLoader + ) + } + def scala = { + val version = args.lift(1).getOrElse(constants.scalaVersion) + val scalac = new ScalaCompilerDependency( version ) + lib.runMain( + "scala.tools.nsc.MainGenericRunner", Seq("-cp", scalac.classpath.string), scalac.classLoader + ) + } } diff --git a/stage2/BuildBuild.scala b/stage2/BuildBuild.scala index 9283cdf..5e0f5d3 100644 --- a/stage2/BuildBuild.scala +++ b/stage2/BuildBuild.scala @@ -3,7 +3,7 @@ import java.io.File import scala.collection.immutable.Seq class BuildBuild(context: Context) extends Build(context){ - override def dependencies = Seq( CbtDependency(context.logger) ) ++ super.dependencies + override def dependencies = Seq( CbtDependency()(context.logger) ) ++ super.dependencies def managedBuildDirectory: File = lib.realpath( projectDirectory.parent ) val managedBuild = { val managedContext = context.copy( cwd = managedBuildDirectory ) diff --git a/stage2/Lib.scala b/stage2/Lib.scala index 6f83859..924a6c0 100644 --- a/stage2/Lib.scala +++ b/stage2/Lib.scala @@ -80,35 +80,29 @@ final class Lib(logger: Logger) extends Stage1Lib(logger) with Scaffold{ } def docJar( + scalaVersion: String, sourceFiles: Seq[File], - dependenyClasspath: ClassPath, + dependencyClasspath: ClassPath, apiTarget: File, jarTarget: File, artifactId: String, version: String, compileArgs: Seq[String] ): File = { - // FIXME: get this dynamically somehow, or is this even needed? - val javacp = ClassPath( - "/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/System/Library/Java/Extensions/MRJToolkit.jar".split(":").toVector.map(new File(_)) - ) - mkdir(Path(apiTarget)) if(sourceFiles.nonEmpty){ - System.err.println("creating docs") + val args = Seq( + // FIXME: can we use compiler dependency here? + "-cp", dependencyClasspath.string, // FIXME: does this break for builds that don't have scalac dependencies? + "-d", apiTarget.toString + ) ++ compileArgs ++ sourceFiles.map(_.toString) + logger.lib("creating docs for source files "+args.mkString(", ")) trapExitCode{ redirectOutToErr{ runMain( "scala.tools.nsc.ScalaDoc", - Seq( - // FIXME: can we use compiler dependency here? - "-cp", /*javacp++":"++*/ScalaDependencies(logger).classpath.string ++ ":" ++ dependenyClasspath.string, - "-d", apiTarget.toString - ) ++ compileArgs ++ sourceFiles.map(_.toString), - new URLClassLoader( - ScalaDependencies(logger).classpath ++ javacp, - ClassLoader.getSystemClassLoader - ) + args, + ScalaDependencies(scalaVersion)(logger).classLoader ) } } diff --git a/stage2/PackageBuild.scala b/stage2/PackageBuild.scala index 96c7b6f..b037e7f 100644 --- a/stage2/PackageBuild.scala +++ b/stage2/PackageBuild.scala @@ -14,12 +14,12 @@ abstract class PackageBuild(context: Context) extends Build(context) with Artifa private object cacheSrcJarBasicBuild extends Cache[File] def srcJar: File = cacheSrcJarBasicBuild{ - lib.srcJar(sources, artifactId, version, scalaTarget) + lib.srcJar( sourceFiles, artifactId, version, scalaTarget ) } private object cacheDocBasicBuild extends Cache[File] def docJar: File = cacheDocBasicBuild{ - lib.docJar( sources, dependencyClasspath, apiTarget, jarTarget, artifactId, version, scalacOptions ) + lib.docJar( scalaVersion, sourceFiles, dependencyClasspath, apiTarget, jarTarget, artifactId, version, scalacOptions ) } override def jars = jar +: dependencyJars -- cgit v1.2.3 From 984a5f1f0f27d191695feeb3410968f2f35f8fc8 Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Fri, 11 Mar 2016 22:36:31 -0500 Subject: Split ClassLoader classes into separate files and a few fixes --- stage1/ClassLoaderCache.scala | 25 +++++++++++++++++ stage1/MultiClassLoader.scala | 24 ++++++++++++++++ stage1/Stage1Lib.scala | 8 ++++++ stage1/URLClassLoader.scala | 22 +++++++++++++++ stage1/classloader.scala | 64 ------------------------------------------- stage2/BasicBuild.scala | 4 +-- test/build/build.scala | 7 +++-- 7 files changed, 85 insertions(+), 69 deletions(-) create mode 100644 stage1/ClassLoaderCache.scala create mode 100644 stage1/MultiClassLoader.scala create mode 100644 stage1/URLClassLoader.scala delete mode 100644 stage1/classloader.scala (limited to 'stage2') diff --git a/stage1/ClassLoaderCache.scala b/stage1/ClassLoaderCache.scala new file mode 100644 index 0000000..ec343f4 --- /dev/null +++ b/stage1/ClassLoaderCache.scala @@ -0,0 +1,25 @@ +package cbt + +import java.net._ + +object ClassLoaderCache{ + private val cache = NailgunLauncher.classLoaderCache + def get( classpath: ClassPath )(implicit logger: Logger): ClassLoader + = cache.synchronized{ + val lib = new Stage1Lib(logger) + val key = classpath.strings.sorted.mkString(":") + if( cache.containsKey(key) ){ + logger.resolver("CACHE HIT: "++key) + cache.get(key) + } else { + logger.resolver("CACHE MISS: "++key) + val cl = new cbt.URLClassLoader( classpath, ClassLoader.getSystemClassLoader ) + cache.put( key, cl ) + cl + } + } + def remove( classpath: ClassPath ) = { + val key = classpath.strings.sorted.mkString(":") + cache.remove( key ) + } +} diff --git a/stage1/MultiClassLoader.scala b/stage1/MultiClassLoader.scala new file mode 100644 index 0000000..de9bd32 --- /dev/null +++ b/stage1/MultiClassLoader.scala @@ -0,0 +1,24 @@ +/* +package cbt +import java.net._ +import scala.util.Try + +import scala.collection.immutable.Seq + + +class MultiClassLoader(parents: Seq[ClassLoader]) extends ClassLoader { + override def loadClass(name: String) = { + //System.err.println("LOADING CLASS "++name); + val c = parents.toStream.map{ + parent => + Try{ + parent.loadClass(name) + }.map(Option[Class[_]](_)).recover{ + case _:ClassNotFoundException => None + }.get + }.find(_.isDefined).flatten + c.getOrElse( ClassLoader.getSystemClassLoader.loadClass(name) ) + } + override def toString = "MultiClassLoader(" ++ parents.mkString(",") ++ ")" +} +*/ diff --git a/stage1/Stage1Lib.scala b/stage1/Stage1Lib.scala index 1ad3030..67ae049 100644 --- a/stage1/Stage1Lib.scala +++ b/stage1/Stage1Lib.scala @@ -190,6 +190,11 @@ class Stage1Lib( val logger: Logger ) extends BaseLib{ } def trapExitCode( code: => Unit ): ExitCode = { + /* + Doesn't seem to work reliably. Seems like the Security manager is not always + reset properly. Maybe some non-thread-safety issue or some Nailgun interaction. + + val old: Option[SecurityManager] = Option(System.getSecurityManager()) try{ val securityManager = new SecurityManager{ @@ -217,6 +222,9 @@ class Stage1Lib( val logger: Logger ) extends BaseLib{ } finally { System.setSecurityManager(old.getOrElse(null)) } + */ + code + ExitCode.Success } } diff --git a/stage1/URLClassLoader.scala b/stage1/URLClassLoader.scala new file mode 100644 index 0000000..870f186 --- /dev/null +++ b/stage1/URLClassLoader.scala @@ -0,0 +1,22 @@ +package cbt + +import java.net._ + +case class URLClassLoader(classPath: ClassPath, parent: ClassLoader) + extends java.net.URLClassLoader( + classPath.strings.map( + path => new URL("file:"++path) + ).toArray, + parent + ){ + override def toString = ( + scala.Console.BLUE ++ "cbt.URLClassLoader" ++ scala.Console.RESET + ++ "(\n " ++ getURLs.map(_.toString).sorted.mkString(",\n ") + ++ ( + if(getParent() != ClassLoader.getSystemClassLoader()) + ",\n" ++ getParent().toString.split("\n").map(" "++_).mkString("\n") + else "" + ) + ++ "\n)" + ) +} diff --git a/stage1/classloader.scala b/stage1/classloader.scala deleted file mode 100644 index 50e33a2..0000000 --- a/stage1/classloader.scala +++ /dev/null @@ -1,64 +0,0 @@ -package cbt -import java.io._ -import java.net._ -import java.nio.file._ -import scala.util.Try - -import scala.collection.immutable.Seq - -object ClassLoaderCache{ - private val cache = NailgunLauncher.classLoaderCache - def get( classpath: ClassPath )(implicit logger: Logger): ClassLoader - = cache.synchronized{ - val lib = new Stage1Lib(logger) - val key = classpath.strings.sorted.mkString(":") - if( cache.containsKey(key) ){ - logger.resolver("CACHE HIT: "++key) - cache.get(key) - } else { - logger.resolver("CACHE MISS: "++key) - val cl = new cbt.URLClassLoader( classpath, ClassLoader.getSystemClassLoader ) - cache.put( key, cl ) - cl - } - } - def remove( classpath: ClassPath ) = { - val key = classpath.strings.sorted.mkString(":") - cache.remove( key ) - } -} -/* -class MultiClassLoader(parents: Seq[ClassLoader]) extends ClassLoader { - override def loadClass(name: String) = { - //System.err.println("LOADING CLASS "++name); - val c = parents.toStream.map{ - parent => - Try{ - parent.loadClass(name) - }.map(Option[Class[_]](_)).recover{ - case _:ClassNotFoundException => None - }.get - }.find(_.isDefined).flatten - c.getOrElse( ClassLoader.getSystemClassLoader.loadClass(name) ) - } - override def toString = "MultiClassLoader(" ++ parents.mkString(",") ++ ")" -} -*/ -case class URLClassLoader(classPath: ClassPath, parent: ClassLoader) - extends java.net.URLClassLoader( - classPath.strings.map( - path => new URL("file:"++path) - ).toArray, - parent - ){ - override def toString = ( - scala.Console.BLUE ++ "cbt.URLClassLoader" ++ scala.Console.RESET - ++ "(\n " ++ getURLs.map(_.toString).sorted.mkString(",\n ") - ++ ( - if(getParent() != ClassLoader.getSystemClassLoader()) - ",\n" ++ getParent().toString.split("\n").map(" "++_).mkString("\n") - else "" - ) - ++ "\n)" - ) -} diff --git a/stage2/BasicBuild.scala b/stage2/BasicBuild.scala index c17bce0..bee58dd 100644 --- a/stage2/BasicBuild.scala +++ b/stage2/BasicBuild.scala @@ -15,10 +15,10 @@ import scala.util._ import ammonite.ops.{cwd => _,_} -class BasicBuild(context: Context) extends Build(context) +class BasicBuild( context: Context ) extends Build( context ) class Build(val context: Context) extends Dependency with TriggerLoop{ // library available to builds - final val logger = context.logger + implicit final val logger: Logger = context.logger override final protected val lib: Lib = new Lib(logger) // ========== general stuff ========== diff --git a/test/build/build.scala b/test/build/build.scala index 92a964b..29665a6 100644 --- a/test/build/build.scala +++ b/test/build/build.scala @@ -1,5 +1,6 @@ -import scala.collection.immutable.Seq +import cbt._ import java.io.File -class Build(context: cbt.Context) extends cbt.Build(context){ - override def dependencies = Seq( cbt.CbtDependency(context.logger) ) ++ super.dependencies +import scala.collection.immutable.Seq +class Build(context: cbt.Context) extends BasicBuild(context){ + override def dependencies = Seq( CbtDependency() ) ++ super.dependencies } -- cgit v1.2.3 From 81259255d6b6bf3d1ef9c3aaadbeae47457f175d Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Fri, 11 Mar 2016 22:43:57 -0500 Subject: only exit with fail if task not found, not if nothing was given --- stage2/Lib.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'stage2') diff --git a/stage2/Lib.scala b/stage2/Lib.scala index 924a6c0..7b07d06 100644 --- a/stage2/Lib.scala +++ b/stage2/Lib.scala @@ -143,7 +143,7 @@ final class Lib(logger: Logger) extends Stage1Lib(logger) with Scaffold{ } class ReflectBuild(val build: Build) extends ReflectObject(build){ - def usage = { + def usage: String = { val baseTasks = lib.taskNames(ru.typeOf[Build]) val thisTasks = lib.taskNames(subclassType) diff baseTasks ( @@ -191,7 +191,9 @@ final class Lib(logger: Logger) extends Stage1Lib(logger) with Scaffold{ System.err.println("") } System.err.println(usage) - System.exit(1) + taskName.foreach{ _ => + System.exit(1) + } } } } -- cgit v1.2.3 From 958e50e5e2f8bc5447071554ad32ef47be1c33ad Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Fri, 11 Mar 2016 23:27:47 -0500 Subject: re-enable usage page tests --- stage2/Stage2.scala | 3 +-- test/test.scala | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 16 deletions(-) (limited to 'stage2') diff --git a/stage2/Stage2.scala b/stage2/Stage2.scala index 392e322..4145e55 100644 --- a/stage2/Stage2.scala +++ b/stage2/Stage2.scala @@ -31,7 +31,7 @@ object Stage2{ val first = lib.loadRoot( context ) val build = first.finalBuild - val res = lib.trapExitCode{ + val res = if (loop) { // TODO: this should allow looping over task specific files, like test files as well val triggerFiles = first.triggerLoopFiles.map(lib.realpath) @@ -54,7 +54,6 @@ object Stage2{ } else { new lib.ReflectBuild(build).callNullary(task) } - } init.logger.stage2(s"[$now] Stage2 end") } diff --git a/test/test.scala b/test/test.scala index deaa46c..7c805c9 100644 --- a/test/test.scala +++ b/test/test.scala @@ -30,19 +30,18 @@ object Main{ logger.test(allArgs.toString) val pb = new ProcessBuilder( allArgs :_* ) pb.directory(cbtHome ++ ("/test/" ++ path)) - val p = pb.inheritIO.start - p.waitFor + val p = pb.start val berr = new BufferedReader(new InputStreamReader(p.getErrorStream)); val bout = new BufferedReader(new InputStreamReader(p.getInputStream)); - p.waitFor import collection.JavaConversions._ val err = Stream.continually(berr.readLine()).takeWhile(_ != null).mkString("\n") val out = Stream.continually(bout.readLine()).takeWhile(_ != null).mkString("\n") - Result(out, err, p.exitValue == 0) + p.waitFor + Result(p.exitValue == 0, out, err) } - case class Result(out: String, err: String, exit0: Boolean) - def assertSuccess(res: Result)(implicit logger: Logger) = { - assert(res.exit0, res.toString) + case class Result(exit0: Boolean, out: String, err: String) + def assertSuccess(res: Result, msg: => String)(implicit logger: Logger) = { + assert(res.exit0, msg + res.toString) } // tests @@ -50,24 +49,25 @@ object Main{ val usageString = "Methods provided by CBT" val res = runCbt(path, Seq()) logger.test(res.toString) - assertSuccess(res) - assert(res.out == "", "usage " + path +" "+ res.toString) - assert(res.err contains usageString, "usage " + path +" "+res.toString) + val debugToken = "usage " + path +" " + assertSuccess(res,debugToken) + assert(res.out == "", debugToken+ res.toString) + assert(res.err contains usageString, debugToken+res.toString) } def compile(path: String)(implicit logger: Logger) = { val res = runCbt(path, Seq("compile")) - assertSuccess(res) + val debugToken = "compile " + path +" " + assertSuccess(res,debugToken) // assert(res.err == "", res.err) // FIXME: enable this } logger.test( "Running tests " ++ args.toList.toString ) - //usage("nothing") + usage("nothing") compile("nothing") - //usage("multi-build") + usage("multi-build") compile("multi-build") - { val noContext = Context(cbtHome ++ "/test/nothing", Seq(), logger) val b = new Build(noContext){ -- cgit v1.2.3 From 55fff670befc97a871cf0f85c65764e108f3d3c1 Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Fri, 11 Mar 2016 23:28:02 -0500 Subject: minor refactorings --- stage1/ClassLoaderCache.scala | 2 +- stage2/Lib.scala | 2 +- stage2/PackageBuild.scala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'stage2') diff --git a/stage1/ClassLoaderCache.scala b/stage1/ClassLoaderCache.scala index ec343f4..18a0d0e 100644 --- a/stage1/ClassLoaderCache.scala +++ b/stage1/ClassLoaderCache.scala @@ -2,7 +2,7 @@ package cbt import java.net._ -object ClassLoaderCache{ +private[cbt] object ClassLoaderCache{ private val cache = NailgunLauncher.classLoaderCache def get( classpath: ClassPath )(implicit logger: Logger): ClassLoader = cache.synchronized{ diff --git a/stage2/Lib.scala b/stage2/Lib.scala index 7b07d06..e87a19d 100644 --- a/stage2/Lib.scala +++ b/stage2/Lib.scala @@ -192,7 +192,7 @@ final class Lib(logger: Logger) extends Stage1Lib(logger) with Scaffold{ } System.err.println(usage) taskName.foreach{ _ => - System.exit(1) + ExitCode.Failure } } } diff --git a/stage2/PackageBuild.scala b/stage2/PackageBuild.scala index b037e7f..4c4e478 100644 --- a/stage2/PackageBuild.scala +++ b/stage2/PackageBuild.scala @@ -2,7 +2,7 @@ package cbt import java.io.File import java.net.URL import scala.collection.immutable.Seq -abstract class PackageBuild(context: Context) extends Build(context) with ArtifactInfo{ +abstract class PackageBuild(context: Context) extends BasicBuild(context) with ArtifactInfo{ def `package`: Seq[File] = lib.concurrently( enableConcurrency )( Seq(() => jar, () => docJar, () => srcJar) )( _() ) -- cgit v1.2.3