mirror of https://github.com/sbt/sbt.git
Minor cleanups
This commit is contained in:
parent
5daf10d6c7
commit
286758e2ba
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue