From 92ed849eaa0c57f5e6bcc2a54a2a080ac44441be Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 22 Dec 2017 10:29:11 +0000 Subject: [PATCH 1/5] Remove import-excluding Predef.conforms As of Scala 2.11 Predef.conforms isn't implicit anymore (and it's deprecated), so import-excluding doesn't avoid the implicit (the implicit version is now Predef.$conforms). Also in Scala 2.13 Predef.conforms has been removed. --- main-actions/src/main/scala/sbt/Package.scala | 1 - main-actions/src/main/scala/sbt/RawCompileLike.scala | 1 - 2 files changed, 2 deletions(-) diff --git a/main-actions/src/main/scala/sbt/Package.scala b/main-actions/src/main/scala/sbt/Package.scala index 080667e6a..82ab1072f 100644 --- a/main-actions/src/main/scala/sbt/Package.scala +++ b/main-actions/src/main/scala/sbt/Package.scala @@ -7,7 +7,6 @@ package sbt -import scala.Predef.{ conforms => _, _ } import java.io.File import java.util.jar.{ Attributes, Manifest } import scala.collection.JavaConverters._ diff --git a/main-actions/src/main/scala/sbt/RawCompileLike.scala b/main-actions/src/main/scala/sbt/RawCompileLike.scala index f8b85e25c..56fc1b551 100644 --- a/main-actions/src/main/scala/sbt/RawCompileLike.scala +++ b/main-actions/src/main/scala/sbt/RawCompileLike.scala @@ -11,7 +11,6 @@ import scala.annotation.tailrec import java.io.File import sbt.internal.inc.{ RawCompiler, ScalaInstance } -import Predef.{ conforms => _, _ } import sbt.io.syntax._ import sbt.io.IO From 5daf10d6c765580c7c859f5409730b908840825d Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 22 Dec 2017 10:54:56 +0000 Subject: [PATCH 2/5] Tweak the description of KList --- .../src/main/scala/sbt/internal/util/KList.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/KList.scala b/internal/util-collection/src/main/scala/sbt/internal/util/KList.scala index 51babcae3..7b7aaf404 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/KList.scala +++ b/internal/util-collection/src/main/scala/sbt/internal/util/KList.scala @@ -10,7 +10,7 @@ package sbt.internal.util import Types._ import Classes.Applicative -/** Heterogeneous list with each element having type M[T] for some type T.*/ +/** A higher-kinded heterogeneous list of elements that share the same type constructor `M[_]`. */ sealed trait KList[+M[_]] { type Transform[N[_]] <: KList[N] From 286758e2ba42f924ff7e1790287435f00ae3c650 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 23 Jan 2018 16:52:51 +0000 Subject: [PATCH 3/5] Minor cleanups --- .../scala/sbt/internal/util/LineReader.scala | 2 +- .../scala/sbt/internal/CommandChannel.scala | 3 +- main/src/main/scala/sbt/BuildSyntax.scala | 2 +- main/src/main/scala/sbt/MainLoop.scala | 24 ++- .../scala/sbt/internal/CommandExchange.scala | 139 ++++++++---------- 5 files changed, 72 insertions(+), 98 deletions(-) diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/LineReader.scala b/internal/util-complete/src/main/scala/sbt/internal/util/LineReader.scala index b5e9d53d2..406ee5e97 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/LineReader.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/LineReader.scala @@ -132,7 +132,7 @@ private[sbt] object JLine { def createReader(): ConsoleReader = createReader(None, JLine.makeInputStream(true)) def createReader(historyPath: Option[File], in: InputStream): ConsoleReader = - usingTerminal { t => + usingTerminal { _ => val cr = new ConsoleReader(in, System.out) cr.setExpandEvents(false) // https://issues.scala-lang.org/browse/SI-7650 cr.setBellEnabled(false) diff --git a/main-command/src/main/scala/sbt/internal/CommandChannel.scala b/main-command/src/main/scala/sbt/internal/CommandChannel.scala index 4fbb9a299..6b1b8e391 100644 --- a/main-command/src/main/scala/sbt/internal/CommandChannel.scala +++ b/main-command/src/main/scala/sbt/internal/CommandChannel.scala @@ -19,8 +19,7 @@ import sjsonnew.JsonFormat */ abstract class CommandChannel { private val commandQueue: ConcurrentLinkedQueue[Exec] = new ConcurrentLinkedQueue() - def append(exec: Exec): Boolean = - commandQueue.add(exec) + def append(exec: Exec): Boolean = commandQueue.add(exec) def poll: Option[Exec] = Option(commandQueue.poll) def publishEvent[A: JsonFormat](event: A, execId: Option[String]): Unit diff --git a/main/src/main/scala/sbt/BuildSyntax.scala b/main/src/main/scala/sbt/BuildSyntax.scala index a2ef2c2cd..527481e87 100644 --- a/main/src/main/scala/sbt/BuildSyntax.scala +++ b/main/src/main/scala/sbt/BuildSyntax.scala @@ -11,7 +11,7 @@ import sbt.internal.DslEntry import sbt.librarymanagement.Configuration private[sbt] trait BuildSyntax { - import language.experimental.macros + import scala.language.experimental.macros def settingKey[T](description: String): SettingKey[T] = macro std.KeyMacro.settingKeyImpl[T] def taskKey[T](description: String): TaskKey[T] = macro std.KeyMacro.taskKeyImpl[T] def inputKey[T](description: String): InputKey[T] = macro std.KeyMacro.inputKeyImpl[T] diff --git a/main/src/main/scala/sbt/MainLoop.scala b/main/src/main/scala/sbt/MainLoop.scala index 110a78fa4..cbcbcb2cf 100644 --- a/main/src/main/scala/sbt/MainLoop.scala +++ b/main/src/main/scala/sbt/MainLoop.scala @@ -7,14 +7,17 @@ package sbt +import java.io.PrintWriter import java.util.Properties + +import jline.TerminalFactory + import scala.annotation.tailrec import scala.util.control.NonFatal -import jline.TerminalFactory import sbt.io.{ IO, Using } import sbt.internal.util.{ ErrorHandling, GlobalLogBacking } -import sbt.internal.util.complete.DefaultParsers +import sbt.internal.util.complete.Parser import sbt.util.Logger import sbt.protocol._ @@ -25,9 +28,7 @@ object MainLoop { // We've disabled jline shutdown hooks to prevent classloader leaks, and have been careful to always restore // the jline terminal in finally blocks, but hitting ctrl+c prevents finally blocks from being executed, in that // case the only way to restore the terminal is in a shutdown hook. - val shutdownHook = new Thread(new Runnable { - def run(): Unit = TerminalFactory.get().restore() - }) + val shutdownHook = new Thread(() => TerminalFactory.get().restore()) try { Runtime.getRuntime.addShutdownHook(shutdownHook) @@ -100,7 +101,7 @@ object MainLoop { /** Runs the next sequence of commands with global logging in place. */ def runWithNewLog(state: State, logBacking: GlobalLogBacking): RunNext = Using.fileWriter(append = true)(logBacking.file) { writer => - val out = new java.io.PrintWriter(writer) + val out = new PrintWriter(writer) val full = state.globalLogging.full val newLogging = state.globalLogging.newAppender(full, out, logBacking) // transferLevels(state, newLogging) @@ -124,7 +125,7 @@ object MainLoop { final class KeepGlobalLog(val state: State) extends RunNext final class Return(val result: xsbti.MainResult) extends RunNext - /** Runs the next sequence of commands that doesn't require global logging changes.*/ + /** Runs the next sequence of commands that doesn't require global logging changes. */ @tailrec def run(state: State): RunNext = state.next match { case State.Continue => run(next(state)) @@ -143,14 +144,11 @@ object MainLoop { /** This is the main function State transfer function of the sbt command processing. */ def processCommand(exec: Exec, state: State): State = { - import DefaultParsers._ val channelName = exec.source map (_.channelName) - StandardMain.exchange publishEventMessage ExecStatusEvent("Processing", - channelName, - exec.execId, - Vector()) + StandardMain.exchange publishEventMessage + ExecStatusEvent("Processing", channelName, exec.execId, Vector()) val parser = Command combine state.definedCommands - val newState = parse(exec.commandLine, parser(state)) match { + val newState = Parser.parse(exec.commandLine, parser(state)) match { case Right(s) => s() // apply command. command side effects happen here case Left(errMsg) => state.log error errMsg diff --git a/main/src/main/scala/sbt/internal/CommandExchange.scala b/main/src/main/scala/sbt/internal/CommandExchange.scala index 2ce2819fa..2ece2e12a 100644 --- a/main/src/main/scala/sbt/internal/CommandExchange.scala +++ b/main/src/main/scala/sbt/internal/CommandExchange.scala @@ -46,46 +46,41 @@ private[sbt] final class CommandExchange { private val autoStartServer = sys.props get "sbt.server.autostart" forall (_.toLowerCase == "true") - private val lock = new AnyRef {} private var server: Option[ServerInstance] = None private val firstInstance: AtomicBoolean = new AtomicBoolean(true) private var consoleChannel: Option[ConsoleChannel] = None private val commandQueue: ConcurrentLinkedQueue[Exec] = new ConcurrentLinkedQueue() private val channelBuffer: ListBuffer[CommandChannel] = new ListBuffer() + private val channelBufferLock = new AnyRef {} private val nextChannelId: AtomicInteger = new AtomicInteger(0) private lazy val jsonFormat = new sjsonnew.BasicJsonProtocol with JValueFormats {} def channels: List[CommandChannel] = channelBuffer.toList - def subscribe(c: CommandChannel): Unit = - lock.synchronized { - channelBuffer.append(c) - } + def subscribe(c: CommandChannel): Unit = channelBufferLock.synchronized(channelBuffer.append(c)) // periodically move all messages from all the channels @tailrec def blockUntilNextExec: Exec = { @tailrec def slurpMessages(): Unit = - (((None: Option[Exec]) /: channels) { _ orElse _.poll }) match { + channels.foldLeft(Option.empty[Exec]) { _ orElse _.poll } match { + case None => () case Some(x) => commandQueue.add(x) slurpMessages - case _ => () } slurpMessages() Option(commandQueue.poll) match { case Some(x) => x - case _ => + case None => Thread.sleep(50) blockUntilNextExec } } def run(s: State): State = { - consoleChannel match { - case Some(_) => // do nothing - case _ => - val x = new ConsoleChannel("console0") - consoleChannel = Some(x) - subscribe(x) + if (consoleChannel.isEmpty) { + val console0 = new ConsoleChannel("console0") + consoleChannel = Some(console0) + subscribe(console0) } if (autoStartServer) runServer(s) else s @@ -97,25 +92,12 @@ private[sbt] final class CommandExchange { * Check if a server instance is running already, and start one if it isn't. */ private[sbt] def runServer(s: State): State = { - lazy val port = (s get serverPort) match { - case Some(x) => x - case None => 5001 - } - lazy val host = (s get serverHost) match { - case Some(x) => x - case None => "127.0.0.1" - } - lazy val auth: Set[ServerAuthentication] = (s get serverAuthentication) match { - case Some(xs) => xs - case None => Set(ServerAuthentication.Token) - } - lazy val connectionType = (s get serverConnectionType) match { - case Some(x) => x - case None => ConnectionType.Tcp - } - lazy val level: Level.Value = (s get serverLogLevel) - .orElse(s get logLevel) - .getOrElse(Level.Warn) + lazy val port = s.get(serverPort).getOrElse(5001) + lazy val host = s.get(serverHost).getOrElse("127.0.0.1") + lazy val auth: Set[ServerAuthentication] = + s.get(serverAuthentication).getOrElse(Set(ServerAuthentication.Token)) + lazy val connectionType = s.get(serverConnectionType).getOrElse(ConnectionType.Tcp) + lazy val level = s.get(serverLogLevel).orElse(s.get(logLevel)).getOrElse(Level.Warn) def onIncomingSocket(socket: Socket, instance: ServerInstance): Unit = { val name = newNetworkName @@ -131,55 +113,50 @@ private[sbt] final class CommandExchange { new NetworkChannel(name, socket, Project structure s, auth, instance, logger) subscribe(channel) } - server match { - case Some(_) => // do nothing - case None if !firstInstance.get => // there's another server - case _ => - val portfile = (new File(".")).getAbsoluteFile / "project" / "target" / "active.json" - val h = Hash.halfHashString(IO.toURI(portfile).toString) - val tokenfile = BuildPaths.getGlobalBase(s) / "server" / h / "token.json" - val socketfile = BuildPaths.getGlobalBase(s) / "server" / h / "sock" - val pipeName = "sbt-server-" + h - val connection = - ServerConnection(connectionType, - host, - port, - auth, - portfile, - tokenfile, - socketfile, - pipeName) - val x = Server.start(connection, onIncomingSocket, s.log) - - // don't throw exception when it times out - val d = "10s" - Try(Await.ready(x.ready, Duration(d))) - x.ready.value match { - case Some(Success(_)) => - // remember to shutdown only when the server comes up - server = Some(x) - case Some(Failure(_: AlreadyRunningException)) => - s.log.warn( - "sbt server could not start because there's another instance of sbt running on this build.") - s.log.warn("Running multiple instances is unsupported") - server = None - firstInstance.set(false) - case Some(Failure(e)) => - s.log.error(e.toString) - server = None - case None => - s.log.warn(s"sbt server could not start in $d") - server = None - firstInstance.set(false) - } + if (server.isEmpty && firstInstance.get) { + val portfile = (new File(".")).getAbsoluteFile / "project" / "target" / "active.json" + val h = Hash.halfHashString(IO.toURI(portfile).toString) + val tokenfile = BuildPaths.getGlobalBase(s) / "server" / h / "token.json" + val socketfile = BuildPaths.getGlobalBase(s) / "server" / h / "sock" + val pipeName = "sbt-server-" + h + val connection = ServerConnection( + connectionType, + host, + port, + auth, + portfile, + tokenfile, + socketfile, + pipeName, + ) + val serverInstance = Server.start(connection, onIncomingSocket, s.log) + // don't throw exception when it times out + val d = "10s" + Try(Await.ready(serverInstance.ready, Duration(d))) + serverInstance.ready.value match { + case Some(Success(())) => + // remember to shutdown only when the server comes up + server = Some(serverInstance) + case Some(Failure(_: AlreadyRunningException)) => + s.log.warn( + "sbt server could not start because there's another instance of sbt running on this build.") + s.log.warn("Running multiple instances is unsupported") + server = None + firstInstance.set(false) + case Some(Failure(e)) => + s.log.error(e.toString) + server = None + case None => + s.log.warn(s"sbt server could not start in $d") + server = None + firstInstance.set(false) + } } s } def shutdown(): Unit = { - channels foreach { c => - c.shutdown() - } + channels foreach (_.shutdown()) // interrupt and kill the thread server.foreach(_.shutdown()) server = None @@ -202,7 +179,7 @@ private[sbt] final class CommandExchange { toDel.toList match { case Nil => // do nothing case xs => - lock.synchronized { + channelBufferLock.synchronized { channelBuffer --= xs () } @@ -241,7 +218,7 @@ private[sbt] final class CommandExchange { toDel.toList match { case Nil => // do nothing case xs => - lock.synchronized { + channelBufferLock.synchronized { channelBuffer --= xs () } @@ -283,7 +260,7 @@ private[sbt] final class CommandExchange { toDel.toList match { case Nil => // do nothing case xs => - lock.synchronized { + channelBufferLock.synchronized { channelBuffer --= xs () } @@ -325,7 +302,7 @@ private[sbt] final class CommandExchange { toDel.toList match { case Nil => // do nothing case xs => - lock.synchronized { + channelBufferLock.synchronized { channelBuffer --= xs () } From 2f48425511d5b4729857b6931fdc40101b89a0d1 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 17 Jan 2018 15:17:56 +0000 Subject: [PATCH 4/5] Remove old zinc addSbtAlternateResolver stuff --- build.sbt | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/build.sbt b/build.sbt index b9d11c0d6..2c860b440 100644 --- a/build.sbt +++ b/build.sbt @@ -537,11 +537,6 @@ def scriptedTask: Def.Initialize[InputTask[Unit]] = Def.inputTask { val result = scriptedSource(dir => (s: State) => Scripted.scriptedParser(dir)).parsed // publishLocalBinAll.value // TODO: Restore scripted needing only binary jars. publishAll.value - // These two projects need to be visible in a repo even if the default - // local repository is hidden, so we publish them to an alternate location and add - // that alternate repo to the running scripted test (in Scripted.scriptedpreScripted). - // (altLocalPublish in interfaceProj).value - // (altLocalPublish in compileInterfaceProj).value Scripted.doScripted( (sbtLaunchJar in bundledLauncherProj).value, (fullClasspath in scriptedSbtProj in Test).value, @@ -599,7 +594,6 @@ def otherRootSettings = scripted := scriptedTask.evaluated, scriptedUnpublished := scriptedUnpublishedTask.evaluated, scriptedSource := (sourceDirectory in sbtProj).value / "sbt-test", - // scriptedPrescripted := { addSbtAlternateResolver _ }, scriptedLaunchOpts := List("-Xmx1500M", "-Xms512M", "-server"), publishAll := { val _ = (publishLocal).all(ScopeFilter(inAnyProject)).value }, publishLocalBinAll := { val _ = (publishLocalBin).all(ScopeFilter(inAnyProject)).value }, @@ -619,23 +613,6 @@ def otherRootSettings = scriptedSource := (sourceDirectory in sbtProj).value / "repo-override-test" )) -// def addSbtAlternateResolver(scriptedRoot: File) = { -// val resolver = scriptedRoot / "project" / "AddResolverPlugin.scala" -// if (!resolver.exists) { -// IO.write(resolver, s"""import sbt._ -// |import Keys._ -// | -// |object AddResolverPlugin extends AutoPlugin { -// | override def requires = sbt.plugins.JvmPlugin -// | override def trigger = allRequirements -// | -// | override lazy val projectSettings = Seq(resolvers += alternativeLocalResolver) -// | lazy val alternativeLocalResolver = Resolver.file("$altLocalRepoName", file("$altLocalRepoPath"))(Resolver.ivyStylePatterns) -// |} -// |""".stripMargin) -// } -// } - lazy val docProjects: ScopeFilter = ScopeFilter( inAnyProject -- inProjects(sbtRoot, sbtProj, scriptedSbtProj, scriptedPluginProj), inConfigurations(Compile) From bee69ebb92906637b6ca9723004bc0ad044816c7 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 17 Jan 2018 15:19:21 +0000 Subject: [PATCH 5/5] Get rid of old MavenResolverPluginTest --- project/Scripted.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/project/Scripted.scala b/project/Scripted.scala index 788f1d60e..bd64b0cfb 100644 --- a/project/Scripted.scala +++ b/project/Scripted.scala @@ -40,8 +40,7 @@ object Scripted { // This is to workaround https://github.com/sbt/io/issues/110 sys.props.put("jna.nosys", "true") - lazy val MavenResolverPluginTest = config("mavenResolverPluginTest") extend Compile - lazy val RepoOverrideTest = config("repoOverrideTest") extend Compile + val RepoOverrideTest = config("repoOverrideTest") extend Compile import sbt.complete._ import DefaultParsers._