From 4fcf253b0e9d2d264074bd7e43d1bc17146e2f7d Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Sun, 16 Aug 2020 11:48:33 -0700 Subject: [PATCH] Allow console terminal opt out While running ~scripted that multiple instance of the console terminal were instantiated which caused problems with reading input. It turned out that RunFromSourceMain was running in the same jvm process as sbt and creating a new console terminal in a different classloader. This both messed up the io of scripted tests when scriptedBufferLog was set to false but it also made it so that I couldn't exit ~ with . To workaround this, I deferred initializaiton of the console terminal to Terminal.withStreams which is guarded by the sbt.io.virtual system property. --- .../scala/sbt/internal/util/Terminal.scala | 22 +++++++++++++------ .../test/scala/sbt/RunFromSourceMain.scala | 1 + 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala b/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala index 929e0f529..15bb3ae40 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala @@ -283,6 +283,8 @@ object Terminal { private[sbt] def withStreams[T](isServer: Boolean)(f: => T): T = if (System.getProperty("sbt.io.virtual", "true") == "true") { hasProgress.set(isServer) + consoleTerminalHolder.set(wrap(jline.TerminalFactory.get)) + activeTerminal.set(consoleTerminalHolder.get) try withOut(withIn(f)) finally { jline.TerminalFactory.reset() @@ -490,7 +492,8 @@ object Terminal { * Terminal.console method returns this terminal and the ConsoleChannel delegates its * terminal method to it. */ - private[this] val consoleTerminalHolder = new AtomicReference(wrap(jline.TerminalFactory.get)) + private[this] val consoleTerminalHolder: AtomicReference[Terminal] = + new AtomicReference(SimpleTerminal) /** * The terminal that is currently being used by the proxyInputStream and proxyOutputStream. @@ -915,7 +918,7 @@ object Terminal { } private lazy val nullWriteableInputStream = new WriteableInputStream(nullInputStream, "null-writeable-input-stream") - private[sbt] val NullTerminal = new Terminal { + private[sbt] class DefaultTerminal extends Terminal { override def close(): Unit = {} override private[sbt] def progressState: ProgressState = new ProgressState(1) override def getBooleanCapability(capability: String, jline3: Boolean): Boolean = false @@ -926,22 +929,27 @@ object Terminal { override def getNumericCapability(capability: String, jline3: Boolean): Integer = null override def getStringCapability(capability: String, jline3: Boolean): String = null override def getWidth: Int = 0 - override def inputStream: java.io.InputStream = nullInputStream + override def inputStream: InputStream = nullInputStream override def isAnsiSupported: Boolean = false override def isColorEnabled: Boolean = false override def isEchoEnabled: Boolean = false override def isSuccessEnabled: Boolean = false override def isSupershellEnabled: Boolean = false - override def outputStream: java.io.OutputStream = _ => {} - override def errorStream: java.io.OutputStream = _ => {} + override def outputStream: OutputStream = _ => {} + override def errorStream: OutputStream = _ => {} override private[sbt] def getAttributes: Map[String, String] = Map.empty override private[sbt] def setAttributes(attributes: Map[String, String]): Unit = {} override private[sbt] def setSize(width: Int, height: Int): Unit = {} override private[sbt] def name: String = "NullTerminal" - override private[sbt] val printStream: java.io.PrintStream = + override private[sbt] val printStream: PrintStream = new PrintStream(outputStream, false) - override private[sbt] def withPrintStream[T](f: java.io.PrintStream => T): T = f(printStream) + override private[sbt] def withPrintStream[T](f: PrintStream => T): T = f(printStream) override private[sbt] def write(bytes: Int*): Unit = {} override private[sbt] def withRawOutput[R](f: => R): R = f } + private[sbt] object NullTerminal extends DefaultTerminal + private[sbt] object SimpleTerminal extends DefaultTerminal { + override lazy val outputStream: OutputStream = originalOut + override lazy val errorStream: OutputStream = originalErr + } } diff --git a/sbt/src/test/scala/sbt/RunFromSourceMain.scala b/sbt/src/test/scala/sbt/RunFromSourceMain.scala index e53ae2b79..24d3991d5 100644 --- a/sbt/src/test/scala/sbt/RunFromSourceMain.scala +++ b/sbt/src/test/scala/sbt/RunFromSourceMain.scala @@ -57,6 +57,7 @@ object RunFromSourceMain { ) case Array(wd, scalaVersion, sbtVersion, classpath, args @ _*) => System.setProperty("jna.nosys", "true") + if (args.exists(_.startsWith("<"))) System.setProperty("sbt.io.virtual", "false") val context = LoggerContext(useLog4J = SysProp.useLog4J) try run(file(wd), scalaVersion, sbtVersion, classpath, args, context) finally context.close()