From b82a1870a7783b57a75d79c6162120c05cb38c54 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 10 Mar 2018 16:50:03 -0500 Subject: [PATCH 01/28] add tests around scope delegation --- main/src/test/scala/Delegates.scala | 51 +++++++++++++++- .../test/scala/sbt/internal/TestBuild.scala | 59 ++++++++++--------- 2 files changed, 81 insertions(+), 29 deletions(-) diff --git a/main/src/test/scala/Delegates.scala b/main/src/test/scala/Delegates.scala index 492cdcdd9..11a511ad4 100644 --- a/main/src/test/scala/Delegates.scala +++ b/main/src/test/scala/Delegates.scala @@ -16,10 +16,10 @@ import Prop._ import Gen._ object Delegates extends Properties("delegates") { - property("generate non-empty configs") = forAll { (c: Seq[Configuration]) => + property("generate non-empty configs") = forAll { (c: Vector[Configuration]) => c.nonEmpty } - property("generate non-empty tasks") = forAll { (t: Seq[Taskk]) => + property("generate non-empty tasks") = forAll { (t: Vector[Taskk]) => t.nonEmpty } @@ -46,6 +46,7 @@ object Delegates extends Properties("delegates") { global forall { _ == Zero } } } + property("Initial scope present with all combinations of Global axes") = allAxes( globalCombinations) @@ -54,12 +55,58 @@ object Delegates extends Properties("delegates") { ds.head == scope } } + property("global scope last") = forAll { (keys: Keys) => allDelegates(keys) { (_, ds) => ds.last == Scope.GlobalScope } } + property("Project axis delegates to BuildRef then Zero") = forAll { (keys: Keys) => + allDelegates(keys) { (key, ds) => + key.project match { + case Zero => true // filtering out of testing + case Select(ProjectRef(uri, _)) => + val buildScoped = key.copy(project = Select(BuildRef(uri))) + val idxKey = ds.indexOf(key) + val idxB = ds.indexOf(buildScoped) + val z = key.copy(project = Zero) + val idxZ = ds.indexOf(z) + if (z == Scope.GlobalScope) true + else { + (s"idxKey = $idxKey; idxB = $idxB; idxZ = $idxZ") |: + (idxKey < idxB) && (idxB < idxZ) + } + case Select(BuildRef(_)) => + ds.indexOf(key) < ds.indexOf(key.copy(project = Zero)) + } + } + } + + property("Config axis delegates to parent configuration") = forAll { (keys: Keys) => + allDelegates(keys) { (key, ds) => + key.config match { + case Zero => true + case Select(config) if key.project.isSelect => + val p = key.project.toOption.get + val r = keys.env.resolve(p) + val proj = keys.env.projectFor(r) + val inh: Vector[ConfigKey] = keys.env.inheritConfig(r, config) + val conf = proj.confMap(config.name) + if (inh.isEmpty) true + else { + val idxKey = ds.indexOf(key) + val parent = inh.head + val a = key.copy(config = Select(parent)) + val idxA = ds.indexOf(a) + (s"idxKey = $idxKey; a = $a; idxA = $idxA") |: + idxKey < idxA + } + case _ => true + } + } + } + def allAxes(f: (Scope, Seq[Scope], Scope => ScopeAxis[_]) => Prop): Prop = forAll { (keys: Keys) => allDelegates(keys) { (s, ds) => diff --git a/main/src/test/scala/sbt/internal/TestBuild.scala b/main/src/test/scala/sbt/internal/TestBuild.scala index 7b8a70db5..7b53b1c7c 100644 --- a/main/src/test/scala/sbt/internal/TestBuild.scala +++ b/main/src/test/scala/sbt/internal/TestBuild.scala @@ -113,7 +113,7 @@ abstract class TestBuild { (taskAxes, zero.toSet, single.toSet, multi.toSet) } } - final class Env(val builds: Seq[Build], val tasks: Seq[Taskk]) { + final class Env(val builds: Vector[Build], val tasks: Vector[Taskk]) { override def toString = "Env:\n " + " Tasks:\n " + tasks.mkString("\n ") + "\n" + builds.mkString("\n ") val root = builds.head @@ -129,20 +129,21 @@ abstract class TestBuild { def inheritConfig(ref: ResolvedReference, config: ConfigKey) = projectFor(ref).confMap(config.name).extendsConfigs map toConfigKey def inheritTask(task: AttributeKey[_]) = taskMap.get(task) match { - case None => Nil; case Some(t) => t.delegates map getKey + case None => Vector() + case Some(t) => t.delegates.toVector map getKey } - def inheritProject(ref: ProjectRef) = project(ref).delegates + def inheritProject(ref: ProjectRef) = project(ref).delegates.toVector def resolve(ref: Reference) = Scope.resolveReference(root.uri, rootProject, ref) lazy val delegates: Scope => Seq[Scope] = Scope.delegates( allProjects, - (_: Proj).configurations.map(toConfigKey), + (_: Proj).configurations.toVector.map(toConfigKey), resolve, uri => buildMap(uri).root.id, inheritProject, inheritConfig, inheritTask, - (ref, mp) => Nil + (ref, mp) => Vector() ) lazy val allFullScopes: Seq[Scope] = for { @@ -262,13 +263,14 @@ abstract class TestBuild { implicit lazy val uriGen: Gen[URI] = for (sch <- idGen; ssp <- idGen; frag <- optIDGen) yield new URI(sch, ssp, frag.orNull) - implicit def envGen(implicit bGen: Gen[Build], tasks: Gen[Seq[Taskk]]): Gen[Env] = - for (i <- MaxBuildsGen; bs <- listOfN(i, bGen); ts <- tasks) yield new Env(bs, ts) + implicit def envGen(implicit bGen: Gen[Build], tasks: Gen[Vector[Taskk]]): Gen[Env] = + for (i <- MaxBuildsGen; bs <- containerOfN[Vector, Build](i, bGen); ts <- tasks) + yield new Env(bs, ts) implicit def buildGen(implicit uGen: Gen[URI], pGen: URI => Gen[Seq[Proj]]): Gen[Build] = for (u <- uGen; ps <- pGen(u)) yield new Build(u, ps) - def nGen[T](igen: Gen[Int])(implicit g: Gen[T]): Gen[List[T]] = igen flatMap { ig => - listOfN(ig, g) + def nGen[T](igen: Gen[Int])(implicit g: Gen[T]): Gen[Vector[T]] = igen flatMap { ig => + containerOfN[Vector, T](ig, g) } implicit def genProjects(build: URI)(implicit genID: Gen[String], @@ -285,34 +287,37 @@ abstract class TestBuild { def genConfigs(implicit genName: Gen[String], maxDeps: Gen[Int], - count: Gen[Int]): Gen[Seq[Configuration]] = + count: Gen[Int]): Gen[Vector[Configuration]] = genAcyclicDirect[Configuration, String](maxDeps, genName, count)( (key, deps) => Configuration .of(key.capitalize, key) .withExtendsConfigs(deps.toVector)) - def genTasks(implicit genName: Gen[String], maxDeps: Gen[Int], count: Gen[Int]): Gen[Seq[Taskk]] = + def genTasks(implicit genName: Gen[String], + maxDeps: Gen[Int], + count: Gen[Int]): Gen[Vector[Taskk]] = genAcyclicDirect[Taskk, String](maxDeps, genName, count)((key, deps) => new Taskk(AttributeKey[String](key), deps)) def genAcyclicDirect[A, T](maxDeps: Gen[Int], keyGen: Gen[T], max: Gen[Int])( - make: (T, Seq[A]) => A): Gen[Seq[A]] = + make: (T, Vector[A]) => A): Gen[Vector[A]] = genAcyclic[A, T](maxDeps, keyGen, max) { t => Gen.const { deps => - make(t, deps) + make(t, deps.toVector) } } def genAcyclic[A, T](maxDeps: Gen[Int], keyGen: Gen[T], max: Gen[Int])( - make: T => Gen[Seq[A] => A]): Gen[Seq[A]] = + make: T => Gen[Vector[A] => A]): Gen[Vector[A]] = max flatMap { count => - listOfN(count, keyGen) flatMap { keys => + containerOfN[Vector, T](count, keyGen) flatMap { keys => genAcyclic(maxDeps, keys.distinct)(make) } } - def genAcyclic[A, T](maxDeps: Gen[Int], keys: List[T])(make: T => Gen[Seq[A] => A]): Gen[Seq[A]] = - genAcyclic(maxDeps, keys, Nil) flatMap { pairs => + def genAcyclic[A, T](maxDeps: Gen[Int], keys: Vector[T])( + make: T => Gen[Vector[A] => A]): Gen[Vector[A]] = + genAcyclic(maxDeps, keys, Vector()) flatMap { pairs => sequence(pairs.map { case (key, deps) => mapMake(key, deps, make) }) flatMap { inputs => val made = new collection.mutable.HashMap[T, A] for ((key, deps, mk) <- inputs) @@ -321,25 +326,25 @@ abstract class TestBuild { } } - def mapMake[A, T](key: T, deps: Seq[T], make: T => Gen[Seq[A] => A]): Gen[Inputs[A, T]] = - make(key) map { (mk: Seq[A] => A) => + def mapMake[A, T](key: T, deps: Vector[T], make: T => Gen[Vector[A] => A]): Gen[Inputs[A, T]] = + make(key) map { (mk: Vector[A] => A) => (key, deps, mk) } def genAcyclic[T](maxDeps: Gen[Int], - names: List[T], - acc: List[Gen[(T, Seq[T])]]): Gen[Seq[(T, Seq[T])]] = + names: Vector[T], + acc: Vector[Gen[(T, Vector[T])]]): Gen[Vector[(T, Vector[T])]] = names match { - case Nil => sequence(acc) - case x :: xs => + case Vector() => sequence(acc) + case Vector(x, xs @ _*) => val next = for (depCount <- maxDeps; d <- pick(depCount min xs.size, xs)) - yield (x, d.toList) - genAcyclic(maxDeps, xs, next :: acc) + yield (x, d.toVector) + genAcyclic(maxDeps, xs.toVector, next +: acc) } - def sequence[T](gs: Seq[Gen[T]]): Gen[Seq[T]] = Gen.parameterized { prms => + def sequence[T](gs: Vector[Gen[T]]): Gen[Vector[T]] = Gen.parameterized { prms => delay(gs map { g => g(prms, seed) getOrElse sys.error("failed generator") }) } - type Inputs[A, T] = (T, Seq[T], Seq[A] => A) + type Inputs[A, T] = (T, Vector[T], Vector[A] => A) } From 67e1e4a9ffb5a2faa47f8d4696204760a83d584c Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 24 Mar 2018 02:07:28 +0900 Subject: [PATCH 02/28] improve server testing previously I was using separate thread in a forked test to test the server, but that is not enough isolation to run multiple server tests. This adds `RunFromSourceMain.fork(workingDirectory: File)`, which allows us to run a fresh sbt on the given working directory. Next, I've refactored the stateful client-side buffer to a class `TestServer`. --- build.sbt | 6 +- .../src/test/scala/sbt/std/TestUtil.scala | 2 +- .../test/scala/sbt/RunFromSourceMain.scala | 21 +- sbt/src/test/scala/sbt/ServerSpec.scala | 193 ------------------ sbt/src/test/scala/testpkg/ServerSpec.scala | 184 +++++++++++++++++ 5 files changed, 207 insertions(+), 199 deletions(-) delete mode 100644 sbt/src/test/scala/sbt/ServerSpec.scala create mode 100644 sbt/src/test/scala/testpkg/ServerSpec.scala diff --git a/build.sbt b/build.sbt index 5e50c04aa..41723a157 100644 --- a/build.sbt +++ b/build.sbt @@ -497,7 +497,6 @@ lazy val sbtProj = (project in file("sbt")) normalizedName := "sbt", crossScalaVersions := Seq(baseScalaVersion), crossPaths := false, - javaOptions ++= Seq("-Xdebug", "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"), mimaSettings, mimaBinaryIssueFilters ++= sbtIgnoredProblems, BuildInfoPlugin.buildInfoDefaultSettings, @@ -506,10 +505,9 @@ lazy val sbtProj = (project in file("sbt")) buildInfoKeys in Test := Seq[BuildInfoKey]( // WORKAROUND https://github.com/sbt/sbt-buildinfo/issues/117 BuildInfoKey.map((fullClasspath in Compile).taskValue) { case (ident, cp) => ident -> cp.files }, + classDirectory in Compile, + classDirectory in Test, ), - connectInput in run in Test := true, - outputStrategy in run in Test := Some(StdoutOutput), - fork in Test := true, ) .configure(addSbtCompilerBridge) diff --git a/main-settings/src/test/scala/sbt/std/TestUtil.scala b/main-settings/src/test/scala/sbt/std/TestUtil.scala index df02fb29c..dc0098f19 100644 --- a/main-settings/src/test/scala/sbt/std/TestUtil.scala +++ b/main-settings/src/test/scala/sbt/std/TestUtil.scala @@ -27,6 +27,6 @@ object TestUtil { val mainClassesDir = buildinfo.TestBuildInfo.classDirectory val testClassesDir = buildinfo.TestBuildInfo.test_classDirectory val depsClasspath = buildinfo.TestBuildInfo.dependencyClasspath - mainClassesDir +: testClassesDir +: depsClasspath mkString ":" + mainClassesDir +: testClassesDir +: depsClasspath mkString java.io.File.pathSeparator } } diff --git a/sbt/src/test/scala/sbt/RunFromSourceMain.scala b/sbt/src/test/scala/sbt/RunFromSourceMain.scala index 6816e24c7..2f4e81a51 100644 --- a/sbt/src/test/scala/sbt/RunFromSourceMain.scala +++ b/sbt/src/test/scala/sbt/RunFromSourceMain.scala @@ -7,14 +7,33 @@ package sbt +import scala.concurrent.Future +import sbt.util.LogExchange import scala.annotation.tailrec - +import buildinfo.TestBuildInfo import xsbti._ object RunFromSourceMain { private val sbtVersion = "1.0.3" // "dev" private val scalaVersion = "2.12.4" + def fork(workingDirectory: File): Future[Unit] = { + val fo = ForkOptions() + .withWorkingDirectory(workingDirectory) + .withOutputStrategy(OutputStrategy.StdoutOutput) + implicit val runner = new ForkRun(fo) + val cp = { + TestBuildInfo.test_classDirectory +: TestBuildInfo.fullClasspath + } + val options = Vector(workingDirectory.toString) + val log = LogExchange.logger("RunFromSourceMain.fork", None, None) + import scala.concurrent.ExecutionContext.Implicits.global + Future { + Run.run("sbt.RunFromSourceMain", cp, options, log) + () + } + } + def main(args: Array[String]): Unit = args match { case Array() => sys.error(s"Must specify working directory as the first argument") case Array(wd, args @ _*) => run(file(wd), args) diff --git a/sbt/src/test/scala/sbt/ServerSpec.scala b/sbt/src/test/scala/sbt/ServerSpec.scala deleted file mode 100644 index a328c6dfe..000000000 --- a/sbt/src/test/scala/sbt/ServerSpec.scala +++ /dev/null @@ -1,193 +0,0 @@ -/* - * sbt - * Copyright 2011 - 2017, Lightbend, Inc. - * Copyright 2008 - 2010, Mark Harrah - * Licensed under BSD-3-Clause license (see LICENSE) - */ - -package sbt - -import org.scalatest._ -import scala.concurrent._ -import scala.annotation.tailrec -import java.io.{ InputStream, OutputStream } -import java.util.concurrent.atomic.AtomicInteger -import java.util.concurrent.{ ThreadFactory, ThreadPoolExecutor } -import sbt.protocol.ClientSocket - -class ServerSpec extends AsyncFlatSpec with Matchers { - import ServerSpec._ - - "server" should "start" in { - withBuildSocket("handshake") { (out, in, tkn) => - writeLine( - """{ "jsonrpc": "2.0", "id": 3, "method": "sbt/setting", "params": { "setting": "root/name" } }""", - out) - Thread.sleep(100) - assert(waitFor(in, 10) { s => - s contains """"id":3""" - }) - } - } - - @tailrec - private[this] def waitFor(in: InputStream, num: Int)(f: String => Boolean): Boolean = { - if (num < 0) false - else - readFrame(in) match { - case Some(x) if f(x) => true - case _ => - waitFor(in, num - 1)(f) - } - } -} - -object ServerSpec { - private val serverTestBase: File = new File(".").getAbsoluteFile / "sbt" / "src" / "server-test" - private val nextThreadId = new AtomicInteger(1) - private val threadGroup = Thread.currentThread.getThreadGroup() - val readBuffer = new Array[Byte](4096) - var buffer: Vector[Byte] = Vector.empty - var bytesRead = 0 - private val delimiter: Byte = '\n'.toByte - private val RetByte = '\r'.toByte - - private val threadFactory = new ThreadFactory() { - override def newThread(runnable: Runnable): Thread = { - val thread = - new Thread(threadGroup, - runnable, - s"sbt-test-server-threads-${nextThreadId.getAndIncrement}") - // Do NOT setDaemon because then the code in TaskExit.scala in sbt will insta-kill - // the backgrounded process, at least for the case of the run task. - thread - } - } - - private val executor = new ThreadPoolExecutor( - 0, /* corePoolSize */ - 1, /* maxPoolSize, max # of servers */ - 2, - java.util.concurrent.TimeUnit.SECONDS, - /* keep alive unused threads this long (if corePoolSize < maxPoolSize) */ - new java.util.concurrent.SynchronousQueue[Runnable](), - threadFactory - ) - - def backgroundRun(baseDir: File, args: Seq[String]): Unit = { - executor.execute(new Runnable { - def run(): Unit = { - RunFromSourceMain.run(baseDir, args) - } - }) - } - - def shutdown(): Unit = executor.shutdown() - - def withBuildSocket(testBuild: String)( - f: (OutputStream, InputStream, Option[String]) => Future[Assertion]): Future[Assertion] = { - IO.withTemporaryDirectory { temp => - IO.copyDirectory(serverTestBase / testBuild, temp / testBuild) - withBuildSocket(temp / testBuild)(f) - } - } - - def sendJsonRpc(message: String, out: OutputStream): Unit = { - writeLine(s"""Content-Length: ${message.size + 2}""", out) - writeLine("", out) - writeLine(message, out) - } - - def readFrame(in: InputStream): Option[String] = { - val l = contentLength(in) - readLine(in) - readLine(in) - readContentLength(in, l) - } - - def contentLength(in: InputStream): Int = { - readLine(in) map { line => - line.drop(16).toInt - } getOrElse (0) - } - - def readLine(in: InputStream): Option[String] = { - if (buffer.isEmpty) { - val bytesRead = in.read(readBuffer) - if (bytesRead > 0) { - buffer = buffer ++ readBuffer.toVector.take(bytesRead) - } - } - val delimPos = buffer.indexOf(delimiter) - if (delimPos > 0) { - val chunk0 = buffer.take(delimPos) - buffer = buffer.drop(delimPos + 1) - // remove \r at the end of line. - val chunk1 = if (chunk0.lastOption contains RetByte) chunk0.dropRight(1) else chunk0 - Some(new String(chunk1.toArray, "utf-8")) - } else None // no EOL yet, so skip this turn. - } - - def readContentLength(in: InputStream, length: Int): Option[String] = { - if (buffer.isEmpty) { - val bytesRead = in.read(readBuffer) - if (bytesRead > 0) { - buffer = buffer ++ readBuffer.toVector.take(bytesRead) - } - } - if (length <= buffer.size) { - val chunk = buffer.take(length) - buffer = buffer.drop(length) - Some(new String(chunk.toArray, "utf-8")) - } else None // have not read enough yet, so skip this turn. - } - - def writeLine(s: String, out: OutputStream): Unit = { - def writeEndLine(): Unit = { - val retByte: Byte = '\r'.toByte - val delimiter: Byte = '\n'.toByte - out.write(retByte.toInt) - out.write(delimiter.toInt) - out.flush - } - - if (s != "") { - out.write(s.getBytes("UTF-8")) - } - writeEndLine - } - - def withBuildSocket(baseDirectory: File)( - f: (OutputStream, InputStream, Option[String]) => Future[Assertion]): Future[Assertion] = { - backgroundRun(baseDirectory, Nil) - - val portfile = baseDirectory / "project" / "target" / "active.json" - - def waitForPortfile(n: Int): Unit = - if (portfile.exists) () - else { - if (n <= 0) sys.error(s"Timeout. $portfile is not found.") - else { - Thread.sleep(1000) - waitForPortfile(n - 1) - } - } - waitForPortfile(10) - val (sk, tkn) = ClientSocket.socket(portfile) - val out = sk.getOutputStream - val in = sk.getInputStream - - sendJsonRpc( - """{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "initializationOptions": { } } }""", - out) - - try { - f(out, in, tkn) - } finally { - sendJsonRpc( - """{ "jsonrpc": "2.0", "id": 9, "method": "sbt/exec", "params": { "commandLine": "exit" } }""", - out) - shutdown() - } - } -} diff --git a/sbt/src/test/scala/testpkg/ServerSpec.scala b/sbt/src/test/scala/testpkg/ServerSpec.scala new file mode 100644 index 000000000..f34eee6b1 --- /dev/null +++ b/sbt/src/test/scala/testpkg/ServerSpec.scala @@ -0,0 +1,184 @@ +/* + * sbt + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under BSD-3-Clause license (see LICENSE) + */ + +package testpkg + +import org.scalatest._ +import scala.concurrent._ +import scala.annotation.tailrec +import sbt.protocol.ClientSocket +import TestServer.withTestServer +import java.io.File +import sbt.io.syntax._ +import sbt.io.IO +import sbt.RunFromSourceMain + +class ServerSpec extends AsyncFreeSpec with Matchers { + "server" - { + "should start" in withTestServer("handshake") { p => + p.writeLine( + """{ "jsonrpc": "2.0", "id": "3", "method": "sbt/setting", "params": { "setting": "root/name" } }""") + assert(p.waitForString(10) { s => + s contains """"id":"3"""" + }) + } + + "return number id when number id is sent" in withTestServer("handshake") { p => + p.writeLine( + """{ "jsonrpc": "2.0", "id": 3, "method": "sbt/setting", "params": { "setting": "root/name" } }""") + assert(p.waitForString(10) { s => + s contains """"id":3""" + }) + } + } +} + +object TestServer { + private val serverTestBase: File = new File(".").getAbsoluteFile / "sbt" / "src" / "server-test" + + def withTestServer(testBuild: String)(f: TestServer => Future[Assertion]): Future[Assertion] = { + IO.withTemporaryDirectory { temp => + IO.copyDirectory(serverTestBase / testBuild, temp / testBuild) + withTestServer(temp / testBuild)(f) + } + } + + def withTestServer(baseDirectory: File)(f: TestServer => Future[Assertion]): Future[Assertion] = { + val testServer = TestServer(baseDirectory) + try { + f(testServer) + } finally { + testServer.bye() + } + } + + def hostLog(s: String): Unit = { + println(s"""[${scala.Console.MAGENTA}build-1${scala.Console.RESET}] $s""") + } +} + +case class TestServer(baseDirectory: File) { + import TestServer.hostLog + + val readBuffer = new Array[Byte](4096) + var buffer: Vector[Byte] = Vector.empty + var bytesRead = 0 + private val delimiter: Byte = '\n'.toByte + private val RetByte = '\r'.toByte + + hostLog("fork to a new sbt instance") + RunFromSourceMain.fork(baseDirectory) + lazy val portfile = baseDirectory / "project" / "target" / "active.json" + + hostLog("wait 30s until the server is ready to respond") + def waitForPortfile(n: Int): Unit = + if (portfile.exists) () + else { + if (n <= 0) sys.error(s"Timeout. $portfile is not found.") + else { + Thread.sleep(1000) + waitForPortfile(n - 1) + } + } + waitForPortfile(30) + + // make connection to the socket described in the portfile + val (sk, tkn) = ClientSocket.socket(portfile) + val out = sk.getOutputStream + val in = sk.getInputStream + + // initiate handshake + sendJsonRpc( + """{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "initializationOptions": { } } }""") + + def test(f: TestServer => Future[Assertion]): Future[Assertion] = { + f(this) + } + + def bye(): Unit = { + hostLog("sending exit") + sendJsonRpc( + """{ "jsonrpc": "2.0", "id": 9, "method": "sbt/exec", "params": { "commandLine": "exit" } }""") + } + + def sendJsonRpc(message: String): Unit = { + writeLine(s"""Content-Length: ${message.size + 2}""") + writeLine("") + writeLine(message) + } + + def writeLine(s: String): Unit = { + def writeEndLine(): Unit = { + val retByte: Byte = '\r'.toByte + val delimiter: Byte = '\n'.toByte + out.write(retByte.toInt) + out.write(delimiter.toInt) + out.flush + } + + if (s != "") { + out.write(s.getBytes("UTF-8")) + } + writeEndLine + } + + def readFrame: Option[String] = { + def getContentLength: Int = { + readLine map { line => + line.drop(16).toInt + } getOrElse (0) + } + + val l = getContentLength + readLine + readLine + readContentLength(l) + } + + @tailrec + final def waitForString(num: Int)(f: String => Boolean): Boolean = { + if (num < 0) false + else + readFrame match { + case Some(x) if f(x) => true + case _ => + waitForString(num - 1)(f) + } + } + + def readLine: Option[String] = { + if (buffer.isEmpty) { + val bytesRead = in.read(readBuffer) + if (bytesRead > 0) { + buffer = buffer ++ readBuffer.toVector.take(bytesRead) + } + } + val delimPos = buffer.indexOf(delimiter) + if (delimPos > 0) { + val chunk0 = buffer.take(delimPos) + buffer = buffer.drop(delimPos + 1) + // remove \r at the end of line. + val chunk1 = if (chunk0.lastOption contains RetByte) chunk0.dropRight(1) else chunk0 + Some(new String(chunk1.toArray, "utf-8")) + } else None // no EOL yet, so skip this turn. + } + + def readContentLength(length: Int): Option[String] = { + if (buffer.isEmpty) { + val bytesRead = in.read(readBuffer) + if (bytesRead > 0) { + buffer = buffer ++ readBuffer.toVector.take(bytesRead) + } + } + if (length <= buffer.size) { + val chunk = buffer.take(length) + buffer = buffer.drop(length) + Some(new String(chunk.toArray, "utf-8")) + } else None // have not read enough yet, so skip this turn. + } + +} From fff32db7ceca4f933dc9a903da76ede4598a468e Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Wed, 28 Mar 2018 17:09:12 -0700 Subject: [PATCH 03/28] Use MacOSXWatchService instead of PollingWatchService This watch service should be more responsive and significantly reduce the disk overhead of the polling based service for large repos. --- main-command/src/main/scala/sbt/Watched.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main-command/src/main/scala/sbt/Watched.scala b/main-command/src/main/scala/sbt/Watched.scala index 8b8385b61..1c2396593 100644 --- a/main-command/src/main/scala/sbt/Watched.scala +++ b/main-command/src/main/scala/sbt/Watched.scala @@ -141,7 +141,7 @@ object Watched { FileSystems.getDefault.newWatchService() case _ if Properties.isMac => // WatchService is slow on macOS - use old polling mode - new PollingWatchService(PollDelay) + new MacOSXWatchService(PollDelay) case _ => FileSystems.getDefault.newWatchService() } From 88f50ce35d006dad6b810c801d10fdb92af3943a Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 30 Mar 2018 23:09:01 -0400 Subject: [PATCH 04/28] Fix console, JLine issue Fixes #3482 --- main-actions/src/main/scala/sbt/Console.scala | 7 +++---- main/src/main/scala/sbt/Defaults.scala | 6 ++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/main-actions/src/main/scala/sbt/Console.scala b/main-actions/src/main/scala/sbt/Console.scala index c2792d595..d94484030 100644 --- a/main-actions/src/main/scala/sbt/Console.scala +++ b/main-actions/src/main/scala/sbt/Console.scala @@ -9,8 +9,8 @@ package sbt import java.io.File import sbt.internal.inc.AnalyzingCompiler +import sbt.internal.util.JLine import sbt.util.Logger - import xsbti.compile.{ Inputs, Compilers } import scala.util.Try @@ -41,11 +41,10 @@ final class Console(compiler: AnalyzingCompiler) { implicit log: Logger): Try[Unit] = { def console0() = compiler.console(classpath, options, initialCommands, cleanupCommands, log)(loader, bindings) - // TODO: Fix JLine - //JLine.withJLine(Run.executeTrapExit(console0, log)) - Run.executeTrapExit(console0, log) + JLine.withJLine(Run.executeTrapExit(console0, log)) } } + object Console { def apply(conf: Inputs): Console = conf.compilers match { diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 3ae24adde..b3fb287e0 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -1373,10 +1373,8 @@ object Defaults extends BuildCommon { val sc = (scalacOptions in task).value val ic = (initialCommands in task).value val cc = (cleanupCommands in task).value - JLine.usingTerminal { _ => - (new Console(compiler))(cpFiles, sc, loader, ic, cc)()(s.log).get - println() - } + (new Console(compiler))(cpFiles, sc, loader, ic, cc)()(s.log).get + println() } private[this] def exported(w: PrintWriter, command: String): Seq[String] => Unit = From 0b801e7598f9cd2076155f7c90c99bf87de6c38e Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 3 Apr 2018 14:25:59 +1000 Subject: [PATCH 05/28] Bump Scala version to 2.12.5 --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 94a583ea8..d7272d442 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -4,7 +4,7 @@ import sbt.contraband.ContrabandPlugin.autoImport._ object Dependencies { // WARNING: Please Scala update versions in PluginCross.scala too - val scala212 = "2.12.4" + val scala212 = "2.12.5" val baseScalaVersion = scala212 // sbt modules From 70d3484896345698d5d142578e451bdb6dcd388a Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 3 Apr 2018 14:27:21 +1000 Subject: [PATCH 06/28] Avoid printing RejectedExectionExeption stack trace after cancellation Before: ``` [warn] /Users/jz/code/zinc/internal/zinc-apiinfo/src/main/scala/xsbt/api/Visit.scala:187:19: parameter value s in method visitString is never used [warn] def visitString(s: String): Unit = () [warn] ^ ^C [warn] Canceling execution... [warn] 10 warnings found [info] Compilation has been cancelled [error] java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ExecutorCompletionService$QueueingFuture@33ec70dd rejected from java.util.concurrent.ThreadPoolExecutor@4b832de6[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 1410] [error] at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063) [error] at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830) [error] at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379) [error] at java.util.concurrent.ExecutorCompletionService.submit(ExecutorCompletionService.java:181) [error] at sbt.CompletionService$.submit(CompletionService.scala:36) [error] at sbt.ConcurrentRestrictions$$anon$4.submitValid(ConcurrentRestrictions.scala:176) [error] at sbt.ConcurrentRestrictions$$anon$4.submit(ConcurrentRestrictions.scala:165) [error] at sbt.Execute.submit(Execute.scala:262) [error] at sbt.Execute.ready(Execute.scala:242) [error] at sbt.Execute.notifyDone(Execute.scala:181) [error] at sbt.Execute.$anonfun$retire$2(Execute.scala:152) [error] at sbt.Execute.$anonfun$retire$2$adapted(Execute.scala:151) [error] at scala.collection.immutable.List.foreach(List.scala:389) [error] at sbt.Execute.retire(Execute.scala:151) [error] at sbt.Execute.$anonfun$work$2(Execute.scala:279) [error] at sbt.Execute$$anon$1.process(Execute.scala:24) [error] at sbt.Execute.next$1(Execute.scala:104) [error] at sbt.Execute.processAll(Execute.scala:107) [error] at sbt.Execute.runKeep(Execute.scala:84) [error] at sbt.EvaluateTask$.liftedTree1$1(EvaluateTask.scala:387) [error] at sbt.EvaluateTask$.run$1(EvaluateTask.scala:386) [error] at sbt.EvaluateTask$.runTask(EvaluateTask.scala:405) [error] at sbt.internal.Aggregation$.$anonfun$timedRun$4(Aggregation.scala:100) [error] at sbt.EvaluateTask$.withStreams(EvaluateTask.scala:331) [error] at sbt.internal.Aggregation$.timedRun(Aggregation.scala:98) [error] at sbt.internal.Aggregation$.runTasks(Aggregation.scala:111) [error] at sbt.internal.Aggregation$.$anonfun$applyTasks$1(Aggregation.scala:68) [error] at sbt.Command$.$anonfun$applyEffect$2(Command.scala:130) [error] at sbt.internal.Aggregation$.$anonfun$evaluatingParser$11(Aggregation.scala:220) [error] at sbt.internal.Act$.$anonfun$actParser0$3(Act.scala:387) [error] at sbt.MainLoop$.processCommand(MainLoop.scala:154) [error] at sbt.MainLoop$.$anonfun$next$2(MainLoop.scala:137) [error] at sbt.State$$anon$1.runCmd$1(State.scala:242) [error] at sbt.State$$anon$1.process(State.scala:248) [error] at sbt.MainLoop$.$anonfun$next$1(MainLoop.scala:137) [error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:16) [error] at sbt.MainLoop$.next(MainLoop.scala:137) [error] at sbt.MainLoop$.run(MainLoop.scala:130) [error] at sbt.MainLoop$.$anonfun$runWithNewLog$1(MainLoop.scala:108) [error] at sbt.io.Using.apply(Using.scala:22) [error] at sbt.MainLoop$.runWithNewLog(MainLoop.scala:102) [error] at sbt.MainLoop$.runAndClearLast(MainLoop.scala:58) [error] at sbt.MainLoop$.runLoggedLoop(MainLoop.scala:43) [error] at sbt.MainLoop$.runLogged(MainLoop.scala:35) [error] at sbt.StandardMain$.runManaged(Main.scala:113) [error] at sbt.xMain.run(Main.scala:76) [error] at xsbt.boot.Launch$$anonfun$run$1.apply(Launch.scala:109) [error] at xsbt.boot.Launch$.withContextLoader(Launch.scala:128) [error] at xsbt.boot.Launch$.run(Launch.scala:109) [error] at xsbt.boot.Launch$$anonfun$apply$1.apply(Launch.scala:35) [error] at xsbt.boot.Launch$.launch(Launch.scala:117) [error] at xsbt.boot.Launch$.apply(Launch.scala:18) [error] at xsbt.boot.Boot$.runImpl(Boot.scala:41) [error] at xsbt.boot.Boot$.main(Boot.scala:17) [error] at xsbt.boot.Boot.main(Boot.scala) [error] java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ExecutorCompletionService$QueueingFuture@33ec70dd rejected from java.util.concurrent.ThreadPoolExecutor@4b832de6[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 1410] [error] Use 'last' for the full log. ``` After: ``` sbt:zinc Root> ;zincIvyIntegration/cleanClasses;zincIvyIntegration/compile [success] Total time: 0 s, completed 03/04/2018 2:24:33 PM [info] Compiling 5 Scala sources and 1 Java source to /Users/jz/code/zinc/internal/zinc-ivy-integration/target/scala-2.12/classes ... [warn] /Users/jz/code/zinc/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ResourceLoader.scala:14:42: parameter value classLoader in method getPropertiesFor is never used [warn] def getPropertiesFor(resource: String, classLoader: ClassLoader): Properties = { [warn] ^ [warn] /Users/jz/code/zinc/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala:13:17: Unused import [warn] import java.net.URLClassLoader [warn] ^ [warn] /Users/jz/code/zinc/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala:137:26: Unused import [warn] import sbt.io.Path.toURLs [warn] ^ [warn] /Users/jz/code/zinc/internal/zinc-ivy-integration/src/main/scala/sbt/internal/inc/ZincComponentCompiler.scala:94:30: The outer reference in this type test cannot be checked at run time. [warn] private final case class ScalaArtifacts(compiler: File, library: File, others: Vector[File]) [warn] ^ ^C [warn] Canceling execution... [warn] four warnings found [info] Compilation has been cancelled [error] Total time: 1 s, completed 03/04/2018 2:24:35 PM ``` Best served with https://github.com/scala/scala/pull/6479 Fixes #3958 --- main/src/main/scala/sbt/EvaluateTask.scala | 7 ++++++- tasks/src/main/scala/sbt/Execute.scala | 11 +++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/main/src/main/scala/sbt/EvaluateTask.scala b/main/src/main/scala/sbt/EvaluateTask.scala index 1d17f5cc3..558fe2daf 100644 --- a/main/src/main/scala/sbt/EvaluateTask.scala +++ b/main/src/main/scala/sbt/EvaluateTask.scala @@ -11,6 +11,7 @@ import sbt.internal.{ Load, BuildStructure, TaskTimings, TaskName, GCUtil } import sbt.internal.util.{ Attributed, ErrorHandling, HList, RMap, Signals, Types } import sbt.util.{ Logger, Show } import sbt.librarymanagement.{ Resolver, UpdateReport } +import java.util.concurrent.RejectedExecutionException import scala.concurrent.duration.Duration import java.io.File @@ -387,7 +388,11 @@ object EvaluateTask { val results = x.runKeep(root)(service) storeValuesForPrevious(results, state, streams) applyResults(results, state, root) - } catch { case inc: Incomplete => (state, Inc(inc)) } finally shutdown() + } catch { + case _: RejectedExecutionException => + (state, Inc(Incomplete(None, message = Some("cancelled")))) + case inc: Incomplete => (state, Inc(inc)) + } finally shutdown() val replaced = transformInc(result) logIncResult(replaced, state, streams) (newState, replaced) diff --git a/tasks/src/main/scala/sbt/Execute.scala b/tasks/src/main/scala/sbt/Execute.scala index 267a1383a..e3030cc00 100644 --- a/tasks/src/main/scala/sbt/Execute.scala +++ b/tasks/src/main/scala/sbt/Execute.scala @@ -7,8 +7,10 @@ package sbt +import java.util.concurrent.RejectedExecutionException + import sbt.internal.util.ErrorHandling.wideConvert -import sbt.internal.util.{ DelegatingPMap, PMap, RMap, IDSet, ~> } +import sbt.internal.util.{ DelegatingPMap, IDSet, PMap, RMap, ~> } import sbt.internal.util.Types._ import Execute._ @@ -76,7 +78,12 @@ private[sbt] final class Execute[A[_] <: AnyRef]( "State: " + state.toString + "\n\nResults: " + results + "\n\nCalls: " + callers + "\n\n" def run[T](root: A[T])(implicit strategy: Strategy): Result[T] = - try { runKeep(root)(strategy)(root) } catch { case i: Incomplete => Inc(i) } + try { + runKeep(root)(strategy)(root) + } catch { + case i: Incomplete => Inc(i) + case _: RejectedExecutionException => Inc(Incomplete(None, message = Some("cancelled"))) + } def runKeep[T](root: A[T])(implicit strategy: Strategy): RMap[A, Result] = { assert(state.isEmpty, "Execute already running/ran.") From d48aa310e6442ff7ed2909c7686496822cea5ab4 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 3 Apr 2018 16:02:52 +0100 Subject: [PATCH 07/28] Catch RejectedExecutionException in Execute#runKeep --- main/src/main/scala/sbt/EvaluateTask.scala | 7 +----- tasks/src/main/scala/sbt/Execute.scala | 29 +++++++++++----------- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/main/src/main/scala/sbt/EvaluateTask.scala b/main/src/main/scala/sbt/EvaluateTask.scala index 558fe2daf..1d17f5cc3 100644 --- a/main/src/main/scala/sbt/EvaluateTask.scala +++ b/main/src/main/scala/sbt/EvaluateTask.scala @@ -11,7 +11,6 @@ import sbt.internal.{ Load, BuildStructure, TaskTimings, TaskName, GCUtil } import sbt.internal.util.{ Attributed, ErrorHandling, HList, RMap, Signals, Types } import sbt.util.{ Logger, Show } import sbt.librarymanagement.{ Resolver, UpdateReport } -import java.util.concurrent.RejectedExecutionException import scala.concurrent.duration.Duration import java.io.File @@ -388,11 +387,7 @@ object EvaluateTask { val results = x.runKeep(root)(service) storeValuesForPrevious(results, state, streams) applyResults(results, state, root) - } catch { - case _: RejectedExecutionException => - (state, Inc(Incomplete(None, message = Some("cancelled")))) - case inc: Incomplete => (state, Inc(inc)) - } finally shutdown() + } catch { case inc: Incomplete => (state, Inc(inc)) } finally shutdown() val replaced = transformInc(result) logIncResult(replaced, state, streams) (newState, replaced) diff --git a/tasks/src/main/scala/sbt/Execute.scala b/tasks/src/main/scala/sbt/Execute.scala index e3030cc00..f063080ca 100644 --- a/tasks/src/main/scala/sbt/Execute.scala +++ b/tasks/src/main/scala/sbt/Execute.scala @@ -78,22 +78,21 @@ private[sbt] final class Execute[A[_] <: AnyRef]( "State: " + state.toString + "\n\nResults: " + results + "\n\nCalls: " + callers + "\n\n" def run[T](root: A[T])(implicit strategy: Strategy): Result[T] = - try { - runKeep(root)(strategy)(root) - } catch { - case i: Incomplete => Inc(i) - case _: RejectedExecutionException => Inc(Incomplete(None, message = Some("cancelled"))) - } - def runKeep[T](root: A[T])(implicit strategy: Strategy): RMap[A, Result] = { - assert(state.isEmpty, "Execute already running/ran.") + try { runKeep(root)(strategy)(root) } catch { case i: Incomplete => Inc(i) } - addNew(root) - processAll() - assert(results contains root, "No result for root node.") - val finalResults = triggers.onComplete(results) - progressState = progress.allCompleted(progressState, finalResults) - finalResults - } + def runKeep[T](root: A[T])(implicit strategy: Strategy): RMap[A, Result] = + try { + assert(state.isEmpty, "Execute already running/ran.") + + addNew(root) + processAll() + assert(results contains root, "No result for root node.") + val finalResults = triggers.onComplete(results) + progressState = progress.allCompleted(progressState, finalResults) + finalResults + } catch { + case _: RejectedExecutionException => throw Incomplete(None, message = Some("cancelled")) + } def processAll()(implicit strategy: Strategy): Unit = { @tailrec def next(): Unit = { From b78a0f667be2c0d27d4f313aeacb98a53833d2cd Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 3 Apr 2018 16:05:56 +0100 Subject: [PATCH 08/28] Catch RejectedExecutionException in CompletionService.submit --- .../main/scala/sbt/CompletionService.scala | 7 ++++-- tasks/src/main/scala/sbt/Execute.scala | 23 ++++++++----------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/tasks/src/main/scala/sbt/CompletionService.scala b/tasks/src/main/scala/sbt/CompletionService.scala index f6fc3a957..88f00a5e8 100644 --- a/tasks/src/main/scala/sbt/CompletionService.scala +++ b/tasks/src/main/scala/sbt/CompletionService.scala @@ -17,7 +17,8 @@ import java.util.concurrent.{ CompletionService => JCompletionService, Executor, Executors, - ExecutorCompletionService + ExecutorCompletionService, + RejectedExecutionException, } object CompletionService { @@ -33,7 +34,9 @@ object CompletionService { def take() = completion.take().get() } def submit[T](work: () => T, completion: JCompletionService[T]): () => T = { - val future = completion.submit { new Callable[T] { def call = work() } } + val future = try completion.submit { new Callable[T] { def call = work() } } catch { + case _: RejectedExecutionException => throw Incomplete(None, message = Some("cancelled")) + } () => future.get() } diff --git a/tasks/src/main/scala/sbt/Execute.scala b/tasks/src/main/scala/sbt/Execute.scala index f063080ca..c5d16288e 100644 --- a/tasks/src/main/scala/sbt/Execute.scala +++ b/tasks/src/main/scala/sbt/Execute.scala @@ -7,8 +7,6 @@ package sbt -import java.util.concurrent.RejectedExecutionException - import sbt.internal.util.ErrorHandling.wideConvert import sbt.internal.util.{ DelegatingPMap, IDSet, PMap, RMap, ~> } import sbt.internal.util.Types._ @@ -80,19 +78,16 @@ private[sbt] final class Execute[A[_] <: AnyRef]( def run[T](root: A[T])(implicit strategy: Strategy): Result[T] = try { runKeep(root)(strategy)(root) } catch { case i: Incomplete => Inc(i) } - def runKeep[T](root: A[T])(implicit strategy: Strategy): RMap[A, Result] = - try { - assert(state.isEmpty, "Execute already running/ran.") + def runKeep[T](root: A[T])(implicit strategy: Strategy): RMap[A, Result] = { + assert(state.isEmpty, "Execute already running/ran.") - addNew(root) - processAll() - assert(results contains root, "No result for root node.") - val finalResults = triggers.onComplete(results) - progressState = progress.allCompleted(progressState, finalResults) - finalResults - } catch { - case _: RejectedExecutionException => throw Incomplete(None, message = Some("cancelled")) - } + addNew(root) + processAll() + assert(results contains root, "No result for root node.") + val finalResults = triggers.onComplete(results) + progressState = progress.allCompleted(progressState, finalResults) + finalResults + } def processAll()(implicit strategy: Strategy): Unit = { @tailrec def next(): Unit = { From 8c1337455da230b8bef98723b354eed0df9f2751 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 4 Apr 2018 14:26:03 +0100 Subject: [PATCH 09/28] Fix migrate URL Fixes #4062 --- main-settings/src/main/scala/sbt/Structure.scala | 2 +- main-settings/src/main/scala/sbt/std/TaskMacro.scala | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/main-settings/src/main/scala/sbt/Structure.scala b/main-settings/src/main/scala/sbt/Structure.scala index bcedc4171..3c643f00d 100644 --- a/main-settings/src/main/scala/sbt/Structure.scala +++ b/main-settings/src/main/scala/sbt/Structure.scala @@ -565,7 +565,7 @@ object Scoped { /** The sbt 0.10 style DSL was deprecated in 0.13.13, favouring the use of the '.value' macro. * - * See http://www.scala-sbt.org/0.13/docs/Migrating-from-sbt-012x.html for how to migrate. + * See http://www.scala-sbt.org/1.x/docs/Migrating-from-sbt-013x.html for how to migrate. */ trait TupleSyntax { import Scoped._ diff --git a/main-settings/src/main/scala/sbt/std/TaskMacro.scala b/main-settings/src/main/scala/sbt/std/TaskMacro.scala index efeff7877..e7ffcee63 100644 --- a/main-settings/src/main/scala/sbt/std/TaskMacro.scala +++ b/main-settings/src/main/scala/sbt/std/TaskMacro.scala @@ -89,12 +89,12 @@ object TaskMacro { final val InputTaskCreateDynName = "createDyn" final val InputTaskCreateFreeName = "createFree" final val append1Migration = - "`<+=` operator is removed. Try `lhs += { x.value }`\n or see http://www.scala-sbt.org/1.0/docs/Migrating-from-sbt-012x.html." + "`<+=` operator is removed. Try `lhs += { x.value }`\n or see http://www.scala-sbt.org/1.x/docs/Migrating-from-sbt-013x.html." final val appendNMigration = - "`<++=` operator is removed. Try `lhs ++= { x.value }`\n or see http://www.scala-sbt.org/1.0/docs/Migrating-from-sbt-012x.html." + "`<++=` operator is removed. Try `lhs ++= { x.value }`\n or see http://www.scala-sbt.org/1.x/docs/Migrating-from-sbt-013x.html." final val assignMigration = """`<<=` operator is removed. Use `key := { x.value }` or `key ~= (old => { newValue })`. - |See http://www.scala-sbt.org/1.0/docs/Migrating-from-sbt-012x.html""".stripMargin + |See http://www.scala-sbt.org/1.x/docs/Migrating-from-sbt-013x.html""".stripMargin import LinterDSL.{ Empty => EmptyLinter } From 04d6a8b44c6b1385ebe84236af332b8de59d644e Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 5 Apr 2018 02:14:00 -0400 Subject: [PATCH 10/28] perf: optimize hash for build This hot path was discovered by retronym using FlameGraph. This removes intermediate creation of Array. `filesModifiedBytes` in particular was bad as it was going through all `*.class` files, each generating an Array. This replaces that with `fileModifiedHash` that accepts `MessageDigest`. According to the flamegraph, evalCommon footprint reduced from 4.5% to 3.6%. Using `time sbt reload reload reload exit`, the median reduced from 41.450s to 39.467s. --- build.sbt | 4 ++ .../src/main/scala/sbt/compiler/Eval.scala | 51 ++++++++++++++----- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/build.sbt b/build.sbt index d2b19aef3..349c89e62 100644 --- a/build.sbt +++ b/build.sbt @@ -310,6 +310,10 @@ lazy val actionsProj = (project in file("main-actions")) name := "Actions", libraryDependencies += sjsonNewScalaJson.value, mimaSettings, + mimaBinaryIssueFilters ++= Seq( + exclude[DirectMissingMethodProblem]("sbt.compiler.Eval.filesModifiedBytes"), + exclude[DirectMissingMethodProblem]("sbt.compiler.Eval.fileModifiedBytes"), + ) ) .configure( addSbtIO, diff --git a/main-actions/src/main/scala/sbt/compiler/Eval.scala b/main-actions/src/main/scala/sbt/compiler/Eval.scala index a9d97246a..d2afb03b9 100644 --- a/main-actions/src/main/scala/sbt/compiler/Eval.scala +++ b/main-actions/src/main/scala/sbt/compiler/Eval.scala @@ -18,6 +18,7 @@ import Tokens.{ EOF, NEWLINE, NEWLINES, SEMI } import java.io.File import java.nio.ByteBuffer import java.net.URLClassLoader +import java.security.MessageDigest import Eval.{ getModule, getValue, WrapValName } import sbt.io.{ DirectoryFilter, FileFilter, GlobFilter, Hash, IO, Path } @@ -159,12 +160,31 @@ final class Eval(optionsNoncp: Seq[String], // TODO - We also encode the source of the setting into the hash to avoid conflicts where the exact SAME setting // is defined in multiple evaluated instances with a backing. This leads to issues with finding a previous // value on the classpath when compiling. - val hash = Hash.toHex( - Hash(bytes( - stringSeqBytes(content) :: optBytes(backing)(fileExistsBytes) :: stringSeqBytes(options) :: - seqBytes(classpath)(fileModifiedBytes) :: stringSeqBytes(imports.strings.map(_._1)) :: optBytes( - tpeName)(bytes) :: - bytes(ev.extraHash) :: Nil))) + + // This is a hot path. + val digester = MessageDigest.getInstance("SHA") + content foreach { c => + digester.update(bytes(c)) + } + backing foreach { x => + digester.update(fileExistsBytes(x)) + } + options foreach { o => + digester.update(bytes(o)) + } + classpath foreach { f => + fileModifiedHash(f, digester) + } + imports.strings.map(_._1) foreach { x => + digester.update(bytes(x)) + } + tpeName foreach { x => + digester.update(bytes(x)) + } + digester.update(bytes(ev.extraHash)) + val d = digester.digest() + + val hash = Hash.toHex(d) val moduleName = makeModuleName(hash) lazy val unit = { @@ -482,13 +502,18 @@ private[sbt] object Eval { def seqBytes[T](s: Seq[T])(f: T => Array[Byte]): Array[Byte] = bytes(s map f) def bytes(b: Seq[Array[Byte]]): Array[Byte] = bytes(b.length) ++ b.flatten.toArray[Byte] def bytes(b: Boolean): Array[Byte] = Array[Byte](if (b) 1 else 0) - def filesModifiedBytes(fs: Array[File]): Array[Byte] = - if (fs eq null) filesModifiedBytes(Array[File]()) else seqBytes(fs)(fileModifiedBytes) - def fileModifiedBytes(f: File): Array[Byte] = - (if (f.isDirectory) - filesModifiedBytes(f listFiles classDirFilter) - else - bytes(IO.getModifiedTimeOrZero(f))) ++ bytes(f.getAbsolutePath) + + // fileModifiedBytes is a hot method, taking up 0.85% of reload time + // This is a procedural version + def fileModifiedHash(f: File, digester: MessageDigest): Unit = { + if (f.isDirectory) + (f listFiles classDirFilter) foreach { x => + fileModifiedHash(x, digester) + } else digester.update(bytes(IO.getModifiedTimeOrZero(f))) + + digester.update(bytes(f.getAbsolutePath)) + } + def fileExistsBytes(f: File): Array[Byte] = bytes(f.exists) ++ bytes(f.getAbsolutePath) From ad3692b2dfc8a7e2164f4a9b7d578a4723daac8c Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 5 Apr 2018 04:22:16 -0400 Subject: [PATCH 11/28] Use NIO Files.getLastModifiedTime for hashing --- main-actions/src/main/scala/sbt/compiler/Eval.scala | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/main-actions/src/main/scala/sbt/compiler/Eval.scala b/main-actions/src/main/scala/sbt/compiler/Eval.scala index d2afb03b9..f9b0ffeee 100644 --- a/main-actions/src/main/scala/sbt/compiler/Eval.scala +++ b/main-actions/src/main/scala/sbt/compiler/Eval.scala @@ -509,11 +509,22 @@ private[sbt] object Eval { if (f.isDirectory) (f listFiles classDirFilter) foreach { x => fileModifiedHash(x, digester) - } else digester.update(bytes(IO.getModifiedTimeOrZero(f))) + } else digester.update(bytes(JavaMilli.getModifiedTimeOrZero(f))) digester.update(bytes(f.getAbsolutePath)) } + // This uses NIO instead of the JNA-based IO.getModifiedTimeOrZero for speed + object JavaMilli { + import java.nio.file.{ Files, NoSuchFileException } + def getModifiedTimeOrZero(f: File): Long = + try { + Files.getLastModifiedTime(f.toPath).toMillis + } catch { + case e: NoSuchFileException => 0L + } + } + def fileExistsBytes(f: File): Array[Byte] = bytes(f.exists) ++ bytes(f.getAbsolutePath) From 4dc76e2b38c7f6f257a638d7a66a7f8838b735c5 Mon Sep 17 00:00:00 2001 From: Jason Steenstra-Pickens Date: Fri, 6 Apr 2018 10:41:31 +1200 Subject: [PATCH 12/28] Add dependencyResolution scoped to updateSbtClassifiers task Fixes #3432 --- main/src/main/scala/sbt/Defaults.scala | 1 + .../update-sbt-classifiers/build.sbt | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index b3fb287e0..c631ff114 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -2168,6 +2168,7 @@ object Classpaths { filterImplicit = false, overrideScalaVersion = true).withScalaOrganization(scalaOrganization.value)) }, + dependencyResolution := IvyDependencyResolution(ivyConfiguration.value), updateSbtClassifiers in TaskGlobal := (Def.task { val lm = dependencyResolution.value val s = streams.value diff --git a/sbt/src/sbt-test/dependency-management/update-sbt-classifiers/build.sbt b/sbt/src/sbt-test/dependency-management/update-sbt-classifiers/build.sbt index b4f691e86..36f0b199b 100644 --- a/sbt/src/sbt-test/dependency-management/update-sbt-classifiers/build.sbt +++ b/sbt/src/sbt-test/dependency-management/update-sbt-classifiers/build.sbt @@ -1 +1,9 @@ scalaVersion := "2.11.11" + +ivyConfiguration := { + throw new RuntimeException("updateSbtClassifiers should use updateSbtClassifiers / ivyConfiguration") +} + +dependencyResolution := { + throw new RuntimeException("updateSbtClassifiers should use updateSbtClassifiers / dependencyResolution") +} From 707bf08c4e46faadce3adbbc8ab4514e3ba5bf4b Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 5 Apr 2018 20:29:26 -0400 Subject: [PATCH 13/28] Add new closewatch mode --- main-command/src/main/scala/sbt/Watched.scala | 6 +++--- project/Dependencies.scala | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/main-command/src/main/scala/sbt/Watched.scala b/main-command/src/main/scala/sbt/Watched.scala index 1c2396593..cff9c1597 100644 --- a/main-command/src/main/scala/sbt/Watched.scala +++ b/main-command/src/main/scala/sbt/Watched.scala @@ -134,14 +134,14 @@ object Watched { AttributeKey[Watched]("watched-configuration", "Configures continuous execution.") def createWatchService(): WatchService = { + def closeWatch = new MacOSXWatchService() sys.props.get("sbt.watch.mode") match { case Some("polling") => new PollingWatchService(PollDelay) case Some("nio") => FileSystems.getDefault.newWatchService() - case _ if Properties.isMac => - // WatchService is slow on macOS - use old polling mode - new MacOSXWatchService(PollDelay) + case Some("closewatch") => closeWatch + case _ if Properties.isMac => closeWatch case _ => FileSystems.getDefault.newWatchService() } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 94a583ea8..88d72b833 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -8,7 +8,7 @@ object Dependencies { val baseScalaVersion = scala212 // sbt modules - private val ioVersion = "1.1.4" + private val ioVersion = "1.1.5" private val utilVersion = "1.1.3" private val lmVersion = "1.1.4" private val zincVersion = "1.1.3" From 8781c16cbb8695a14a11b3372eaca4971e7bf56b Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 6 Apr 2018 16:30:33 -0400 Subject: [PATCH 14/28] bump IO and Zinc --- .../src/main/scala/sbt/compiler/Eval.scala | 19 ++++++++----------- project/Dependencies.scala | 4 ++-- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/main-actions/src/main/scala/sbt/compiler/Eval.scala b/main-actions/src/main/scala/sbt/compiler/Eval.scala index f9b0ffeee..56fbce162 100644 --- a/main-actions/src/main/scala/sbt/compiler/Eval.scala +++ b/main-actions/src/main/scala/sbt/compiler/Eval.scala @@ -15,7 +15,7 @@ import ast.parser.Tokens import reporters.{ ConsoleReporter, Reporter } import scala.reflect.internal.util.{ AbstractFileClassLoader, BatchSourceFile } import Tokens.{ EOF, NEWLINE, NEWLINES, SEMI } -import java.io.File +import java.io.{ File, FileNotFoundException } import java.nio.ByteBuffer import java.net.URLClassLoader import java.security.MessageDigest @@ -509,21 +509,18 @@ private[sbt] object Eval { if (f.isDirectory) (f listFiles classDirFilter) foreach { x => fileModifiedHash(x, digester) - } else digester.update(bytes(JavaMilli.getModifiedTimeOrZero(f))) + } else digester.update(bytes(getModifiedTimeOrZero(f))) digester.update(bytes(f.getAbsolutePath)) } // This uses NIO instead of the JNA-based IO.getModifiedTimeOrZero for speed - object JavaMilli { - import java.nio.file.{ Files, NoSuchFileException } - def getModifiedTimeOrZero(f: File): Long = - try { - Files.getLastModifiedTime(f.toPath).toMillis - } catch { - case e: NoSuchFileException => 0L - } - } + def getModifiedTimeOrZero(f: File): Long = + try { + sbt.io.JavaMilli.getModifiedTime(f.getPath) + } catch { + case _: FileNotFoundException => 0L + } def fileExistsBytes(f: File): Array[Byte] = bytes(f.exists) ++ diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 88d72b833..50d38e300 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -8,10 +8,10 @@ object Dependencies { val baseScalaVersion = scala212 // sbt modules - private val ioVersion = "1.1.5" + private val ioVersion = "1.1.6" private val utilVersion = "1.1.3" private val lmVersion = "1.1.4" - private val zincVersion = "1.1.3" + private val zincVersion = "1.1.4" private val sbtIO = "org.scala-sbt" %% "io" % ioVersion From 32385c8bb7985fb3bc545c59f6c8bc1292f0e283 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 6 Apr 2018 18:36:10 -0400 Subject: [PATCH 15/28] launcher 1.0.4 --- project/Dependencies.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 50d38e300..6ee63a29c 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -26,8 +26,9 @@ object Dependencies { private val libraryManagementCore = "org.scala-sbt" %% "librarymanagement-core" % lmVersion private val libraryManagementIvy = "org.scala-sbt" %% "librarymanagement-ivy" % lmVersion - val launcherInterface = "org.scala-sbt" % "launcher-interface" % "1.0.3" - val rawLauncher = "org.scala-sbt" % "launcher" % "1.0.3" + val launcherVersion = "1.0.4" + val launcherInterface = "org.scala-sbt" % "launcher-interface" % launcherVersion + val rawLauncher = "org.scala-sbt" % "launcher" % launcherVersion val testInterface = "org.scala-sbt" % "test-interface" % "1.0" val ipcSocket = "org.scala-sbt.ipcsocket" % "ipcsocket" % "1.0.0" From 1abb0a3641e68b635f5f50229c21cfb96eff85d1 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sun, 8 Apr 2018 14:31:48 +1000 Subject: [PATCH 16/28] Upgrade to latest sbt-houserules --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index c91a3bc6f..68b01d14b 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,7 +1,7 @@ scalaVersion := "2.12.4" scalacOptions ++= Seq("-feature", "-language:postfixOps") -addSbtPlugin("org.scala-sbt" % "sbt-houserules" % "0.3.5") +addSbtPlugin("org.scala-sbt" % "sbt-houserules" % "0.3.6") addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.4.0") addSbtPlugin("de.heikoseeberger" % "sbt-header" % "3.0.2") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.8.0") From 8ed796fb2570956a2edfa9cc36e4c80ddb05438b Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 9 Apr 2018 00:11:17 -0400 Subject: [PATCH 17/28] Re-fixing console and JLine Fixes #3482 take 2 I thought I tested #4054 using a local build, but when I ran 1.1.3, `console` did not display anything that I typed. Switching to `usingTerminal` which calls `terminal.restore` similar to what I had in 1.1.1 fixes `console`. --- main-actions/src/main/scala/sbt/Console.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main-actions/src/main/scala/sbt/Console.scala b/main-actions/src/main/scala/sbt/Console.scala index d94484030..61bfb9e47 100644 --- a/main-actions/src/main/scala/sbt/Console.scala +++ b/main-actions/src/main/scala/sbt/Console.scala @@ -41,7 +41,9 @@ final class Console(compiler: AnalyzingCompiler) { implicit log: Logger): Try[Unit] = { def console0() = compiler.console(classpath, options, initialCommands, cleanupCommands, log)(loader, bindings) - JLine.withJLine(Run.executeTrapExit(console0, log)) + JLine.usingTerminal { _ => + Run.executeTrapExit(console0, log) + } } } From b9eb7764f3d28c7b30bbf3ceb641afde9f583e3f Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 9 Apr 2018 12:37:42 -0400 Subject: [PATCH 18/28] Zinc 1.1.5 --- build.sbt | 2 +- project/Dependencies.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 349c89e62..a45918803 100644 --- a/build.sbt +++ b/build.sbt @@ -9,7 +9,7 @@ def buildLevelSettings: Seq[Setting[_]] = inThisBuild( Seq( organization := "org.scala-sbt", - version := "1.1.3-SNAPSHOT", + version := "1.1.4-SNAPSHOT", description := "sbt is an interactive build tool", bintrayOrganization := Some("sbt"), bintrayRepository := { diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 6ee63a29c..5705334fa 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -11,7 +11,7 @@ object Dependencies { private val ioVersion = "1.1.6" private val utilVersion = "1.1.3" private val lmVersion = "1.1.4" - private val zincVersion = "1.1.4" + private val zincVersion = "1.1.5" private val sbtIO = "org.scala-sbt" %% "io" % ioVersion From e5a37cad429bcfc7d74a8820c13be3381cc5f2fe Mon Sep 17 00:00:00 2001 From: Heikki Vesalainen Date: Wed, 11 Apr 2018 00:10:56 +0300 Subject: [PATCH 19/28] Update to Jline 2.14.6 This version of Jline fixes three things for Emacs users: - ANSI colors are now enabled for Emacs. - Terminal echo is now disabled for Emacs. - History is enabled for all dump terminals. --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 5705334fa..56706d639 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -98,7 +98,7 @@ object Dependencies { "com.eed3si9n" %% "sjson-new-scalajson" % contrabandSjsonNewVersion.value } - val jline = "jline" % "jline" % "2.14.4" + val jline = "jline" % "jline" % "2.14.6" val scalatest = "org.scalatest" %% "scalatest" % "3.0.4" val scalaCheck = "org.scalacheck" %% "scalacheck" % "1.13.4" val specs2 = "org.specs2" %% "specs2-junit" % "4.0.1" From a1e3146c0865f085b5ac65966561efc02c16e922 Mon Sep 17 00:00:00 2001 From: Alexey Alekhin Date: Wed, 11 Apr 2018 18:37:16 +0200 Subject: [PATCH 20/28] Don't use initialize request id for the internal collectAnalyses call --- .../main/scala/sbt/internal/server/LanguageServerProtocol.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/src/main/scala/sbt/internal/server/LanguageServerProtocol.scala b/main/src/main/scala/sbt/internal/server/LanguageServerProtocol.scala index 77314890a..af5b37337 100644 --- a/main/src/main/scala/sbt/internal/server/LanguageServerProtocol.scala +++ b/main/src/main/scala/sbt/internal/server/LanguageServerProtocol.scala @@ -64,7 +64,7 @@ private[sbt] trait LanguageServerProtocol extends CommandChannel { else throw LangServerError(ErrorCodes.InvalidRequest, "invalid token") } else () setInitialized(true) - append(Exec(s"collectAnalyses", Some(request.id), Some(CommandSource(name)))) + append(Exec(s"collectAnalyses", None, Some(CommandSource(name)))) langRespond(InitializeResult(serverCapabilities), Option(request.id)) case "textDocument/definition" => import scala.concurrent.ExecutionContext.Implicits.global From 2bb717dbf97f94bdc6d7259654757dea2a278b35 Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Wed, 11 Apr 2018 18:51:53 -0700 Subject: [PATCH 21/28] Exclude directories instead of including files The existing filter caused SourceModificationWatch.watch to ignore deleted files because !file.exists implies !file.isFile. The intention of the filter was to exclude directories that had a name ending in ".scala". --- main/src/main/scala/sbt/Defaults.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index c631ff114..82af2a9e4 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -162,8 +162,7 @@ object Defaults extends BuildCommon { artifactClassifier in packageSrc :== Some(SourceClassifier), artifactClassifier in packageDoc :== Some(DocClassifier), includeFilter :== NothingFilter, - includeFilter in unmanagedSources :== ("*.java" | "*.scala") && new SimpleFileFilter( - _.isFile), + includeFilter in unmanagedSources :== ("*.java" | "*.scala") -- DirectoryFilter, includeFilter in unmanagedJars :== "*.jar" | "*.so" | "*.dll" | "*.jnilib" | "*.zip", includeFilter in unmanagedResources :== AllPassFilter, bgList := { bgJobService.value.jobs }, From 1ec07c1867d2b7eb01503f68e0fc43d84f445911 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 26 Mar 2018 10:37:25 -0400 Subject: [PATCH 22/28] Recover sbtOn --- build.sbt | 4 ++++ sbt/src/test/scala/sbt/RunFromSourceMain.scala | 17 +++++++++-------- sbt/src/test/scala/testpkg/ServerSpec.scala | 6 +++++- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/build.sbt b/build.sbt index 41723a157..01f18a2a8 100644 --- a/build.sbt +++ b/build.sbt @@ -497,6 +497,7 @@ lazy val sbtProj = (project in file("sbt")) normalizedName := "sbt", crossScalaVersions := Seq(baseScalaVersion), crossPaths := false, + javaOptions ++= Seq("-Xdebug", "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"), mimaSettings, mimaBinaryIssueFilters ++= sbtIgnoredProblems, BuildInfoPlugin.buildInfoDefaultSettings, @@ -508,6 +509,9 @@ lazy val sbtProj = (project in file("sbt")) classDirectory in Compile, classDirectory in Test, ), + Test / run / connectInput := true, + Test / run / outputStrategy := Some(StdoutOutput), + Test / run / fork := true, ) .configure(addSbtCompilerBridge) diff --git a/sbt/src/test/scala/sbt/RunFromSourceMain.scala b/sbt/src/test/scala/sbt/RunFromSourceMain.scala index 2f4e81a51..c0bd9cfc1 100644 --- a/sbt/src/test/scala/sbt/RunFromSourceMain.scala +++ b/sbt/src/test/scala/sbt/RunFromSourceMain.scala @@ -7,7 +7,7 @@ package sbt -import scala.concurrent.Future +import scala.util.Try import sbt.util.LogExchange import scala.annotation.tailrec import buildinfo.TestBuildInfo @@ -17,21 +17,22 @@ object RunFromSourceMain { private val sbtVersion = "1.0.3" // "dev" private val scalaVersion = "2.12.4" - def fork(workingDirectory: File): Future[Unit] = { + def fork(workingDirectory: File): Try[Unit] = { val fo = ForkOptions() - .withWorkingDirectory(workingDirectory) .withOutputStrategy(OutputStrategy.StdoutOutput) + fork(fo, workingDirectory) + } + + def fork(fo0: ForkOptions, workingDirectory: File): Try[Unit] = { + val fo = fo0 + .withWorkingDirectory(workingDirectory) implicit val runner = new ForkRun(fo) val cp = { TestBuildInfo.test_classDirectory +: TestBuildInfo.fullClasspath } val options = Vector(workingDirectory.toString) val log = LogExchange.logger("RunFromSourceMain.fork", None, None) - import scala.concurrent.ExecutionContext.Implicits.global - Future { - Run.run("sbt.RunFromSourceMain", cp, options, log) - () - } + Run.run("sbt.RunFromSourceMain", cp, options, log) } def main(args: Array[String]): Unit = args match { diff --git a/sbt/src/test/scala/testpkg/ServerSpec.scala b/sbt/src/test/scala/testpkg/ServerSpec.scala index f34eee6b1..259e5c248 100644 --- a/sbt/src/test/scala/testpkg/ServerSpec.scala +++ b/sbt/src/test/scala/testpkg/ServerSpec.scala @@ -71,7 +71,11 @@ case class TestServer(baseDirectory: File) { private val RetByte = '\r'.toByte hostLog("fork to a new sbt instance") - RunFromSourceMain.fork(baseDirectory) + import scala.concurrent.ExecutionContext.Implicits.global + Future { + RunFromSourceMain.fork(baseDirectory) + () + } lazy val portfile = baseDirectory / "project" / "target" / "active.json" hostLog("wait 30s until the server is ready to respond") From eeeb4c9ff2e047599b9bbc83a1dcd8951cf9ddad Mon Sep 17 00:00:00 2001 From: OlegYch Date: Mon, 23 Apr 2018 20:46:08 +0300 Subject: [PATCH 23/28] Remove usage of DynamicVariable and fix memory leak, fixes https://github.com/sbt/sbt/issues/4112 --- build.sbt | 2 ++ .../scala/sbt/JUnitXmlTestsListener.scala | 23 ++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/build.sbt b/build.sbt index 5baf26bfc..c1e10290a 100644 --- a/build.sbt +++ b/build.sbt @@ -220,6 +220,8 @@ lazy val testingProj = (project in file("testing")) exclude[DirectMissingMethodProblem]("sbt.protocol.testing.TestItemEvent.copy$default$*"), exclude[DirectMissingMethodProblem]("sbt.protocol.testing.TestStringEvent.copy"), exclude[DirectMissingMethodProblem]("sbt.protocol.testing.TestStringEvent.copy$default$1"), + //no reason to use + exclude[DirectMissingMethodProblem]("sbt.JUnitXmlTestsListener.testSuite"), ) ) .configure(addSbtIO, addSbtCompilerClasspath, addSbtUtilLogging) diff --git a/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala b/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala index 3e62dcea2..29a4ebc8c 100644 --- a/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala +++ b/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala @@ -12,7 +12,6 @@ import java.net.InetAddress import java.util.Hashtable import scala.collection.mutable.ListBuffer -import scala.util.DynamicVariable import scala.xml.{ Elem, Node => XNode, XML } import testing.{ Event => TEvent, @@ -124,21 +123,28 @@ class JUnitXmlTestsListener(val outputDir: String) extends TestsListener { } /**The currently running test suite*/ - val testSuite = new DynamicVariable(null: TestSuite) + private val testSuite = new InheritableThreadLocal[Option[TestSuite]] { + override def initialValue(): Option[TestSuite] = None + } + + private def withTestSuite[T](f: TestSuite => T) = + testSuite.get().map(f).getOrElse(sys.error("no test suite")) /**Creates the output Dir*/ - override def doInit() = { targetDir.mkdirs() } + override def doInit() = { + val _ = targetDir.mkdirs() + } /** * Starts a new, initially empty Suite with the given name. */ - override def startGroup(name: String): Unit = testSuite.value_=(new TestSuite(name)) + override def startGroup(name: String): Unit = testSuite.set(Some(new TestSuite(name))) /** * Adds all details for the given even to the current suite. */ override def testEvent(event: TestEvent): Unit = for (e <- event.detail) { - testSuite.value.addEvent(e) + withTestSuite(_.addEvent(e)) } /** @@ -174,7 +180,7 @@ class JUnitXmlTestsListener(val outputDir: String) extends TestsListener { def selector = null def throwable = new OptionalThrowable(t) } - testSuite.value.addEvent(event) + withTestSuite(_.addEvent(event)) writeSuite() } @@ -191,10 +197,11 @@ class JUnitXmlTestsListener(val outputDir: String) extends TestsListener { private[this] def normalizeName(s: String) = s.replaceAll("""\s+""", "-") private def writeSuite() = { - val file = new File(targetDir, s"${normalizeName(testSuite.value.name)}.xml").getAbsolutePath + val file = new File(targetDir, s"${normalizeName(withTestSuite(_.name))}.xml").getAbsolutePath // TODO would be nice to have a logger and log this with level debug // System.err.println("Writing JUnit XML test report: " + file) - XML.save(file, testSuite.value.stop(), "UTF-8", true, null) + XML.save(file, withTestSuite(_.stop()), "UTF-8", true, null) + testSuite.remove() } /**Does nothing, as we write each file after a suite is done.*/ From 065b65a05e25885840c1f713ef16cffeb6a1f8af Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 24 Apr 2018 07:29:49 +0100 Subject: [PATCH 24/28] Drop -Ywarn-unused:-params Previously we'd get in the build logs: [error] params cannot be negated, it enables other arguments and lots of wawrnings. Now we just get lots of warnings without the non-fatal error message. --- project/Util.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Util.scala b/project/Util.scala index 8c68f4ced..d2141341b 100644 --- a/project/Util.scala +++ b/project/Util.scala @@ -48,7 +48,7 @@ object Util { "-Yno-adapted-args", "-Ywarn-dead-code", "-Ywarn-numeric-widen", - "-Ywarn-unused:-patvars,-params,-implicits,_", + "-Ywarn-unused:-patvars,-implicits,_", "-Ywarn-unused-import" ) }), From 334789c919eb3c9fed2670fb26e3a53e7e2dc6dc Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Wed, 25 Apr 2018 16:15:19 -0400 Subject: [PATCH 25/28] 1.1.5-SNAPSHOT --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c1e10290a..33480b08c 100644 --- a/build.sbt +++ b/build.sbt @@ -9,7 +9,7 @@ def buildLevelSettings: Seq[Setting[_]] = inThisBuild( Seq( organization := "org.scala-sbt", - version := "1.1.4-SNAPSHOT", + version := "1.1.5-SNAPSHOT", description := "sbt is an interactive build tool", bintrayOrganization := Some("sbt"), bintrayRepository := { From a798c4adffb66b631c6965bf53a999037f05323b Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Wed, 25 Apr 2018 16:55:26 -0400 Subject: [PATCH 26/28] Re-fix console and JLine bug Fixes #3482 take 3 There are two bugs related REPL and JLine. 1. JLine getting disabled (up arrow not working) on the second run of `console` task. 2. Typed characters not showing up even on the `console` task. The first issue was fixed by #4054 which added `t.init`. When I noticed the second problem, I fixed it in #4082 (adds `t.restore`) but undid the first fix. This attempts to fix both the issues. --- main-actions/src/main/scala/sbt/Console.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main-actions/src/main/scala/sbt/Console.scala b/main-actions/src/main/scala/sbt/Console.scala index 61bfb9e47..9bc20d676 100644 --- a/main-actions/src/main/scala/sbt/Console.scala +++ b/main-actions/src/main/scala/sbt/Console.scala @@ -41,7 +41,8 @@ final class Console(compiler: AnalyzingCompiler) { implicit log: Logger): Try[Unit] = { def console0() = compiler.console(classpath, options, initialCommands, cleanupCommands, log)(loader, bindings) - JLine.usingTerminal { _ => + JLine.usingTerminal { t => + t.init Run.executeTrapExit(console0, log) } } From e72696480956ce7a078a036c06eb6fea138351e6 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 27 Apr 2018 19:59:56 -0400 Subject: [PATCH 27/28] Bump npm modules for VS Code extension --- vscode-sbt-scala/client/package-lock.json | 1033 ++++++++++++--------- vscode-sbt-scala/client/package.json | 5 +- vscode-sbt-scala/package-lock.json | 12 +- vscode-sbt-scala/package.json | 4 +- vscode-sbt-scala/server/package-lock.json | 56 +- 5 files changed, 625 insertions(+), 485 deletions(-) diff --git a/vscode-sbt-scala/client/package-lock.json b/vscode-sbt-scala/client/package-lock.json index c20e59f73..7b49514a7 100644 --- a/vscode-sbt-scala/client/package-lock.json +++ b/vscode-sbt-scala/client/package-lock.json @@ -1,16 +1,42 @@ { "name": "vscode-sbt-scala", - "version": "0.0.2", + "version": "0.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "requires": { + "ansi-wrap": "0.1.0" } }, "ansi-regex": { @@ -23,12 +49,18 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + }, "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", "requires": { - "arr-flatten": "1.1.0" + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" } }, "arr-flatten": { @@ -36,11 +68,21 @@ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=" + }, "array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=" + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -85,9 +127,9 @@ "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" }, "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" }, "balanced-match": { "version": "1.0.0", @@ -122,12 +164,19 @@ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "requires": { "hoek": "2.16.3" + }, + "dependencies": { + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + } } }, "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { "balanced-match": "1.0.0", "concat-map": "0.0.1" @@ -153,6 +202,11 @@ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, + "buffer-from": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==" + }, "caseless": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", @@ -171,9 +225,9 @@ } }, "clone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", - "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" }, "clone-buffer": { "version": "1.0.0", @@ -186,13 +240,13 @@ "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" }, "cloneable-readable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", "requires": { "inherits": "2.0.3", - "process-nextick-args": "1.0.7", - "through2": "2.0.3" + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.6" } }, "co": { @@ -200,18 +254,23 @@ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { "delayed-stream": "1.0.0" } }, "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" }, "concat-map": { "version": "0.0.1", @@ -219,9 +278,9 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "convert-source-map": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=" + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" }, "core-util-is": { "version": "1.0.2", @@ -252,14 +311,14 @@ } }, "dateformat": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", - "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" }, "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "requires": { "ms": "2.0.0" } @@ -278,9 +337,9 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=" + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==" }, "duplexer": { "version": "0.1.1", @@ -319,13 +378,13 @@ } }, "duplexify": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", + "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", "requires": { - "end-of-stream": "1.4.0", + "end-of-stream": "1.4.1", "inherits": "2.0.3", - "readable-stream": "2.3.3", + "readable-stream": "2.3.6", "stream-shift": "1.0.0" } }, @@ -339,9 +398,9 @@ } }, "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "requires": { "once": "1.4.0" } @@ -387,11 +446,11 @@ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" }, "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", "requires": { - "is-extendable": "0.1.1" + "kind-of": "1.1.0" } }, "extglob": { @@ -415,14 +474,25 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fancy-log": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", - "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "requires": { - "chalk": "1.1.3", + "ansi-gray": "0.1.1", + "color-support": "1.1.3", "time-stamp": "1.1.0" } }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, "fd-slicer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", @@ -477,8 +547,8 @@ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "requires": { "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" + "combined-stream": "1.0.6", + "mime-types": "2.1.18" } }, "from": { @@ -644,9 +714,9 @@ } }, "glogg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", - "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", "requires": { "sparkles": "1.0.0" } @@ -656,15 +726,10 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" - }, "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=" + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" }, "gulp-chmod": { "version": "2.0.0", @@ -677,29 +742,24 @@ } }, "gulp-filter": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.0.1.tgz", - "integrity": "sha512-5olRzAhFdXB2klCu1lnazP65aO9YdA/5WfC9VdInIc8PrUeDIoZfaA3Edb0yUBGhVdHv4eHKL9Fg5tUoEJ9z5A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.1.0.tgz", + "integrity": "sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM=", "requires": { - "gulp-util": "3.0.8", "multimatch": "2.1.0", - "streamfilter": "1.0.5" + "plugin-error": "0.1.2", + "streamfilter": "1.0.7" } }, "gulp-gunzip": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/gulp-gunzip/-/gulp-gunzip-0.0.3.tgz", - "integrity": "sha1-e24HsPWP09QlFcSOrVpj3wVy9i8=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz", + "integrity": "sha1-FbdBFF6Dqcb1CIYkG1fMWHHxUak=", "requires": { "through2": "0.6.5", "vinyl": "0.4.6" }, "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" - }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -729,15 +789,6 @@ "readable-stream": "1.0.34", "xtend": "4.0.1" } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } } } }, @@ -753,25 +804,25 @@ "vinyl": "2.0.2" }, "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, "clone-stats": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" - }, "request": { "version": "2.79.0", "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", "requires": { "aws-sign2": "0.6.0", - "aws4": "1.6.0", + "aws4": "1.7.0", "caseless": "0.11.0", - "combined-stream": "1.0.5", + "combined-stream": "1.0.6", "extend": "3.0.1", "forever-agent": "0.6.1", "form-data": "2.1.4", @@ -781,13 +832,13 @@ "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", + "mime-types": "2.1.18", "oauth-sign": "0.8.2", "qs": "6.3.2", "stringstream": "0.0.5", - "tough-cookie": "2.3.2", + "tough-cookie": "2.3.4", "tunnel-agent": "0.4.3", - "uuid": "3.1.0" + "uuid": "3.2.1" } }, "vinyl": { @@ -795,10 +846,10 @@ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.0.2.tgz", "integrity": "sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw=", "requires": { - "clone": "1.0.2", + "clone": "1.0.4", "clone-buffer": "1.0.0", "clone-stats": "1.0.0", - "cloneable-readable": "1.0.0", + "cloneable-readable": "1.1.2", "is-stream": "1.1.0", "remove-trailing-separator": "1.1.0", "replace-ext": "1.0.0" @@ -811,19 +862,29 @@ "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", "requires": { - "convert-source-map": "1.5.0", + "convert-source-map": "1.5.1", "graceful-fs": "4.1.11", "strip-bom": "2.0.0", "through2": "2.0.3", "vinyl": "1.2.0" }, "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + }, "vinyl": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "requires": { - "clone": "1.0.2", + "clone": "1.0.4", "clone-stats": "0.0.1", "replace-ext": "0.0.1" } @@ -862,8 +923,8 @@ "array-uniq": "1.0.3", "beeper": "1.1.1", "chalk": "1.1.3", - "dateformat": "2.0.0", - "fancy-log": "1.3.0", + "dateformat": "2.2.0", + "fancy-log": "1.3.2", "gulplog": "1.0.0", "has-gulplog": "0.1.0", "lodash._reescape": "3.0.0", @@ -876,64 +937,83 @@ "replace-ext": "0.0.1", "through2": "2.0.3", "vinyl": "0.5.3" - } - }, - "gulp-vinyl-zip": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-1.4.0.tgz", - "integrity": "sha1-VjgvLMtXIxuwR4x4c3zNVylzvuE=", - "requires": { - "event-stream": "3.3.4", - "queue": "3.1.0", - "through2": "0.6.5", - "vinyl": "0.4.6", - "vinyl-fs": "2.4.4", - "yauzl": "2.8.0", - "yazl": "2.4.2" }, "dependencies": { "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" }, - "isarray": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" + }, + "replace-ext": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "clone": "1.0.4", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" } + } + } + }, + "gulp-vinyl-zip": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.0.tgz", + "integrity": "sha1-JOQGhdwFtxSZlSRQmeBZAmO+ja0=", + "requires": { + "event-stream": "3.3.4", + "queue": "4.4.2", + "through2": "2.0.3", + "vinyl": "2.1.0", + "vinyl-fs": "2.4.4", + "yauzl": "2.9.1", + "yazl": "2.4.3" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "queue": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-4.4.2.tgz", + "integrity": "sha512-fSMRXbwhMwipcDZ08enW2vl+YDmAmhcNcr43sCJL8DIg+CFOsoRLG23ctxA+fwNk1w55SePSiS7oqQQSgQoVJQ==", "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "inherits": "2.0.3" } }, "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" } } } @@ -943,13 +1023,13 @@ "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "requires": { - "glogg": "1.0.0" + "glogg": "1.0.1" } }, "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { "version": "2.0.6", @@ -957,8 +1037,8 @@ "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", "requires": { "chalk": "1.1.3", - "commander": "2.11.0", - "is-my-json-valid": "2.16.1", + "commander": "2.15.1", + "is-my-json-valid": "2.17.2", "pinkie-promise": "2.0.1" } }, @@ -971,9 +1051,9 @@ } }, "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, "has-gulplog": { "version": "0.1.0", @@ -992,6 +1072,13 @@ "cryptiles": "2.0.5", "hoek": "2.16.3", "sntp": "1.0.9" + }, + "dependencies": { + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + } } }, "he": { @@ -1000,9 +1087,9 @@ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" }, "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" }, "http-signature": { "version": "1.1.1", @@ -1011,7 +1098,7 @@ "requires": { "assert-plus": "0.2.0", "jsprim": "1.4.1", - "sshpk": "1.13.1" + "sshpk": "1.14.1" } }, "inflight": { @@ -1034,9 +1121,9 @@ "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=" }, "is-buffer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-dotfile": { "version": "1.0.3", @@ -1069,13 +1156,19 @@ "is-extglob": "2.1.1" } }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==" + }, "is-my-json-valid": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", "requires": { "generate-function": "2.0.0", "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", "jsonpointer": "4.0.1", "xtend": "4.0.1" } @@ -1086,6 +1179,16 @@ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "requires": { "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } } }, "is-obj": { @@ -1157,6 +1260,11 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, "json-stable-stringify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", @@ -1170,11 +1278,6 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" - }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", @@ -1204,28 +1307,16 @@ } }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.5" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=" }, "lazystream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", "requires": { - "readable-stream": "2.3.3" - } - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" + "readable-stream": "2.3.6" } }, "lodash._basecopy": { @@ -1233,11 +1324,6 @@ "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=" - }, "lodash._basetostring": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", @@ -1278,16 +1364,6 @@ "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" - } - }, "lodash.escape": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", @@ -1361,7 +1437,7 @@ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", "requires": { - "readable-stream": "2.3.3" + "readable-stream": "2.3.6" } }, "micromatch": { @@ -1384,6 +1460,14 @@ "regex-cache": "0.4.4" }, "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "1.1.0" + } + }, "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", @@ -1396,20 +1480,28 @@ "requires": { "is-extglob": "1.0.0" } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } } } }, "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" }, "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "requires": { - "mime-db": "1.30.0" + "mime-db": "1.33.0" } }, "minimatch": { @@ -1417,13 +1509,13 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "1.1.11" } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mkdirp": { "version": "0.5.1", @@ -1431,61 +1523,36 @@ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - } } }, "mocha": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", "requires": { "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", + "glob": "7.1.2", + "growl": "1.10.3", "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", "mkdirp": "0.5.1", - "supports-color": "3.1.2" + "supports-color": "4.4.0" }, "dependencies": { "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "requires": { - "graceful-readlink": "1.0.1" - } - }, - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" }, "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", "requires": { - "has-flag": "1.0.0" + "has-flag": "2.0.0" } } } @@ -1536,9 +1603,9 @@ "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" }, "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object.omit": { "version": "2.0.1", @@ -1563,7 +1630,7 @@ "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", "requires": { "is-stream": "1.1.0", - "readable-stream": "2.3.3" + "readable-stream": "2.3.6" } }, "parse-glob": { @@ -1616,9 +1683,9 @@ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" }, "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pinkie": { "version": "2.0.4", @@ -1633,15 +1700,27 @@ "pinkie": "2.0.4" } }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "requires": { + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" + } + }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" }, "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "punycode": { "version": "1.4.1", @@ -1654,9 +1733,9 @@ "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=" }, "querystringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", + "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==" }, "queue": { "version": "3.1.0", @@ -1688,7 +1767,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "requires": { - "is-buffer": "1.1.5" + "is-buffer": "1.1.6" } } } @@ -1698,22 +1777,22 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "requires": { - "is-buffer": "1.1.5" + "is-buffer": "1.1.6" } } } }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, @@ -1741,64 +1820,144 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" }, "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", + "aws-sign2": "0.7.0", + "aws4": "1.7.0", "caseless": "0.12.0", - "combined-stream": "1.0.5", + "combined-stream": "1.0.6", "extend": "3.0.1", "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", + "mime-types": "2.1.18", "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.1.1", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.2", "stringstream": "0.0.5", - "tough-cookie": "2.3.2", + "tough-cookie": "2.3.4", "tunnel-agent": "0.6.0", - "uuid": "3.1.0" + "uuid": "3.2.1" }, "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.1" + } + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" } }, "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.1" + } }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "5.1.2" } } } @@ -1817,14 +1976,14 @@ } }, "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" }, "sntp": { "version": "1.0.9", @@ -1832,19 +1991,27 @@ "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "requires": { "hoek": "2.16.3" + }, + "dependencies": { + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + } } }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.5.tgz", + "integrity": "sha512-mR7/Nd5l1z6g99010shcXJiNEaf3fEtmLhRB/sBcQVJGodcHCULPp2y4Sfa43Kv2zq7T+Izmfp/WHCR6dYkQCA==", "requires": { - "source-map": "0.5.7" + "buffer-from": "1.0.0", + "source-map": "0.6.1" } }, "sparkles": { @@ -1861,9 +2028,9 @@ } }, "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", "requires": { "asn1": "0.2.3", "assert-plus": "1.0.0", @@ -1901,11 +2068,11 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" }, "streamfilter": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.5.tgz", - "integrity": "sha1-h1BxEb644phFFxe1Ec/tjwAqv1M=", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.7.tgz", + "integrity": "sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ==", "requires": { - "readable-stream": "2.3.3" + "readable-stream": "2.3.6" } }, "streamifier": { @@ -1914,11 +2081,11 @@ "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=" }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "5.1.2" } }, "stringstream": { @@ -1976,7 +2143,7 @@ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "requires": { - "readable-stream": "2.3.3", + "readable-stream": "2.3.6", "xtend": "4.0.1" } }, @@ -2000,12 +2167,22 @@ "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", "requires": { "extend-shallow": "2.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } } }, "tough-cookie": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", - "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "requires": { "punycode": "1.4.1" } @@ -2031,11 +2208,11 @@ } }, "url-parse": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.1.9.tgz", - "integrity": "sha1-xn8dd11R8KGJEd17P/rSe7nlvRk=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.0.tgz", + "integrity": "sha512-ERuGxDiQ6Xw/agN4tuoCRbmwRuZP0cJ1lJxJubXr5Q/5cDa78+Dc4wfvtxzhzhkm5VvmW6Mf8EVj9SPGN4l8Lg==", "requires": { - "querystringify": "1.0.0", + "querystringify": "2.0.0", "requires-port": "1.0.0" } }, @@ -2045,9 +2222,9 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" }, "vali-date": { "version": "1.0.0", @@ -2072,13 +2249,12 @@ } }, "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "requires": { - "clone": "1.0.2", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" + "clone": "0.2.0", + "clone-stats": "0.0.1" } }, "vinyl-fs": { @@ -2086,7 +2262,7 @@ "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", "requires": { - "duplexify": "3.5.1", + "duplexify": "3.5.4", "glob-stream": "5.3.5", "graceful-fs": "4.1.11", "gulp-sourcemaps": "1.6.0", @@ -2096,7 +2272,7 @@ "merge-stream": "1.0.1", "mkdirp": "0.5.1", "object-assign": "4.1.1", - "readable-stream": "2.3.3", + "readable-stream": "2.3.6", "strip-bom": "2.0.0", "strip-bom-stream": "1.0.0", "through2": "2.0.3", @@ -2105,17 +2281,22 @@ "vinyl": "1.2.0" }, "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" }, "vinyl": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "requires": { - "clone": "1.0.2", + "clone": "1.0.4", "clone-stats": "0.0.1", "replace-ext": "0.0.1" } @@ -2123,108 +2304,64 @@ } }, "vinyl-source-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz", - "integrity": "sha1-RMvlEIIFJ53rDFZTwJSiiHk4sas=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz", + "integrity": "sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A=", "requires": { - "through2": "0.6.5", + "through2": "2.0.3", "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } } }, "vscode": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.5.tgz", - "integrity": "sha1-EOsQQAGEDD3QgTgV/UoF+PyILRQ=", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.16.tgz", + "integrity": "sha512-nNsfYANLqqNfa2+flHyrIrqSIumIoV7R+R9H3gn0SAzZL3RGPEy8db3EYjXKPW5NEfssj/HZhSMI3J3pMNmhPA==", "requires": { "glob": "7.1.2", "gulp-chmod": "2.0.0", - "gulp-filter": "5.0.1", - "gulp-gunzip": "0.0.3", + "gulp-filter": "5.1.0", + "gulp-gunzip": "1.0.0", "gulp-remote-src": "0.4.3", "gulp-symdest": "1.1.0", "gulp-untar": "0.0.6", - "gulp-vinyl-zip": "1.4.0", - "mocha": "3.5.3", - "request": "2.81.0", - "semver": "5.4.1", - "source-map-support": "0.4.18", - "url-parse": "1.1.9", - "vinyl-source-stream": "1.1.0" + "gulp-vinyl-zip": "2.1.0", + "mocha": "4.1.0", + "request": "2.85.0", + "semver": "5.5.0", + "source-map-support": "0.5.5", + "url-parse": "1.4.0", + "vinyl-source-stream": "1.1.2" } }, - "vscode-jsonrpc": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.4.0.tgz", - "integrity": "sha1-qpWsWDvzHYD3JdV8J8CfTCz+n6k=" - }, "vscode-languageclient": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-3.4.2.tgz", - "integrity": "sha1-LtbuoHJVC6q8m9MkgP8CeHVZiXI=", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-3.5.1.tgz", + "integrity": "sha512-GTQ+hSq/o4c/y6GYmyP9XNrVoIu0NFZ67KltSkqN+tO0eUNDIlrVNX+3DJzzyLhSsrctuGzuYWm3t87mNAcBmQ==", "requires": { - "vscode-languageserver-protocol": "3.4.1" + "vscode-languageserver-protocol": "3.5.1" + }, + "dependencies": { + "vscode-jsonrpc": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz", + "integrity": "sha1-hyOdnhZrLXNSJFuKgTWXgEwdY6o=" + }, + "vscode-languageserver-protocol": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.1.tgz", + "integrity": "sha512-1fPDIwsAv1difCV+8daOrJEGunClNJWqnUHq/ncWrjhitKWXgGmRCjlwZ3gDUTt54yRcvXz1PXJDaRNvNH6pYA==", + "requires": { + "vscode-jsonrpc": "3.5.0", + "vscode-languageserver-types": "3.5.0" + } + }, + "vscode-languageserver-types": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz", + "integrity": "sha1-5I15li8LjgLelV4/UkkI4rGcA3Q=" + } } }, - "vscode-languageserver-protocol": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.4.1.tgz", - "integrity": "sha1-lrfIo+1opOvTCkB7BCenY3k1/h8=", - "requires": { - "vscode-jsonrpc": "3.4.0", - "vscode-languageserver-types": "3.4.0" - } - }, - "vscode-languageserver-types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.4.0.tgz", - "integrity": "sha1-UEOuR+5KwWrwe7PQylYSNeDA0vo=" - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -2236,18 +2373,18 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "yauzl": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz", - "integrity": "sha1-eUUK/yKyqcWkHvVOAtuQfM+/nuI=", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", "requires": { "buffer-crc32": "0.2.13", "fd-slicer": "1.0.1" } }, "yazl": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.4.2.tgz", - "integrity": "sha1-FMsZCD4eJacAksFYiqvg9OTdTYg=", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.4.3.tgz", + "integrity": "sha1-7CblzIfVYBud+EMtvdPNLlFzoHE=", "requires": { "buffer-crc32": "0.2.13" } diff --git a/vscode-sbt-scala/client/package.json b/vscode-sbt-scala/client/package.json index c8d8a4472..1e729fc32 100644 --- a/vscode-sbt-scala/client/package.json +++ b/vscode-sbt-scala/client/package.json @@ -52,7 +52,8 @@ "postinstall": "node ./node_modules/vscode/bin/install" }, "dependencies": { - "vscode": "^1.1.5", - "vscode-languageclient": "^3.4.2" + "vscode": "^1.1.16", + "vscode-languageclient": "^3.4.2", + "hoek": "^4.2.1" } } diff --git a/vscode-sbt-scala/package-lock.json b/vscode-sbt-scala/package-lock.json index 5b8616285..71296d214 100644 --- a/vscode-sbt-scala/package-lock.json +++ b/vscode-sbt-scala/package-lock.json @@ -11,15 +11,15 @@ "dev": true }, "@types/node": { - "version": "6.0.88", - "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.88.tgz", - "integrity": "sha512-bYDPZTX0/s1aihdjLuAgogUAT5M+TpoWChEMea2p0yOcfn5bu3k6cJb9cp6nw268XeSNIGGr+4+/8V5K6BGzLQ==", + "version": "7.0.61", + "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.61.tgz", + "integrity": "sha512-X4MNN+Z36OmVPv7n08wxq46/t61/rauW4+xeyxGPueDQ9t7SetHnuEPS0p9n6wU/15HvJLGjzfLTc/RwN7id3A==", "dev": true }, "typescript": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.5.2.tgz", - "integrity": "sha1-A4qV99m7tCCxvzW6MdTFwd0//jQ=", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.8.3.tgz", + "integrity": "sha512-K7g15Bb6Ra4lKf7Iq2l/I5/En+hLIHmxWZGq3D4DIRNFxMNV6j2SHSvDOqs2tGd4UvD/fJvrwopzQXjLrT7Itw==", "dev": true } } diff --git a/vscode-sbt-scala/package.json b/vscode-sbt-scala/package.json index e57bb7b9a..256dadcca 100644 --- a/vscode-sbt-scala/package.json +++ b/vscode-sbt-scala/package.json @@ -20,7 +20,7 @@ }, "devDependencies": { "@types/mocha": "^2.2.42", - "@types/node": "^6.0.88", - "typescript": "^2.5.2" + "@types/node": "^7.0.10", + "typescript": "^2.7.2" } } diff --git a/vscode-sbt-scala/server/package-lock.json b/vscode-sbt-scala/server/package-lock.json index d56b2fe0e..0b52e89e7 100644 --- a/vscode-sbt-scala/server/package-lock.json +++ b/vscode-sbt-scala/server/package-lock.json @@ -4,38 +4,40 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "vscode-jsonrpc": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.4.0.tgz", - "integrity": "sha1-qpWsWDvzHYD3JdV8J8CfTCz+n6k=" - }, "vscode-languageserver": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-3.4.2.tgz", - "integrity": "sha1-CMvlDuJpAdN91LXcUsJbkJNjwfE=", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-3.5.1.tgz", + "integrity": "sha512-RYUKn0DgHTFcS8kS4VaNCjNMaQXYqiXdN9bKrFjXzu5RPKfjIYcoh47oVWwZj4L3R/DPB0Se7HPaDatvYY2XgQ==", "requires": { - "vscode-languageserver-protocol": "3.4.1", - "vscode-uri": "1.0.1" + "vscode-languageserver-protocol": "3.5.1", + "vscode-uri": "1.0.3" + }, + "dependencies": { + "vscode-jsonrpc": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz", + "integrity": "sha1-hyOdnhZrLXNSJFuKgTWXgEwdY6o=" + }, + "vscode-languageserver-protocol": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.1.tgz", + "integrity": "sha512-1fPDIwsAv1difCV+8daOrJEGunClNJWqnUHq/ncWrjhitKWXgGmRCjlwZ3gDUTt54yRcvXz1PXJDaRNvNH6pYA==", + "requires": { + "vscode-jsonrpc": "3.5.0", + "vscode-languageserver-types": "3.5.0" + } + }, + "vscode-languageserver-types": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz", + "integrity": "sha1-5I15li8LjgLelV4/UkkI4rGcA3Q=" + } } }, - "vscode-languageserver-protocol": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.4.1.tgz", - "integrity": "sha1-lrfIo+1opOvTCkB7BCenY3k1/h8=", - "requires": { - "vscode-jsonrpc": "3.4.0", - "vscode-languageserver-types": "3.4.0" - } - }, - "vscode-languageserver-types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.4.0.tgz", - "integrity": "sha1-UEOuR+5KwWrwe7PQylYSNeDA0vo=" - }, "vscode-uri": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.1.tgz", - "integrity": "sha1-Eahr7+rDxKo+wIYjZRo8gabQu8g=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.3.tgz", + "integrity": "sha1-Yxvb9xbcyrDmUpGo3CXCMjIIWlI=" } } } From 4086f6c85b6466957ba29100e15c8e33ace1cf7e Mon Sep 17 00:00:00 2001 From: Robert Walker Date: Sat, 28 Apr 2018 19:44:15 -0400 Subject: [PATCH 28/28] start sbt in VS Code terminal window --- vscode-sbt-scala/client/src/extension.ts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/vscode-sbt-scala/client/src/extension.ts b/vscode-sbt-scala/client/src/extension.ts index 768e0fc03..c5d3a1282 100644 --- a/vscode-sbt-scala/client/src/extension.ts +++ b/vscode-sbt-scala/client/src/extension.ts @@ -3,10 +3,30 @@ import * as path from 'path'; let fs = require('fs'); +import * as vscode from 'vscode'; import { ExtensionContext, workspace } from 'vscode'; // workspace, import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient'; -export function activate(context: ExtensionContext) { +export async function activate(context: ExtensionContext) { + // Start sbt + const terminal = vscode.window.createTerminal(`sbt`); + terminal.show(); + terminal.sendText("sbt"); + + function delay(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + // Wait for SBT server to start + let retries = 30; + while (retries > 0) { + retries--; + await delay(1000); + if (fs.existsSync(path.join(workspace.rootPath, 'project', 'target', 'active.json'))) { + break; + } + } + // The server is implemented in node let serverModule = context.asAbsolutePath(path.join('server', 'server.js')); // The debug options for the server