diff --git a/.travis.yml b/.travis.yml index b0bab8379..b859331fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,10 @@ jdk: oraclejdk8 scala: - 2.11.11 - - 2.12.2 + - 2.12.3 script: - - sbt -Dfile.encoding=UTF8 -J-XX:ReservedCodeCacheSize=256M "++$TRAVIS_SCALA_VERSION" test + - sbt -Dfile.encoding=UTF8 -J-XX:ReservedCodeCacheSize=256M "++$TRAVIS_SCALA_VERSION" mimaReportBinaryIssues test cache: directories: diff --git a/build.sbt b/build.sbt index 3f8885f73..4015f18d7 100644 --- a/build.sbt +++ b/build.sbt @@ -1,6 +1,6 @@ import Dependencies._ import Util._ -// import com.typesafe.tools.mima.core._, ProblemFilters._ +//import com.typesafe.tools.mima.core._, ProblemFilters._ def baseVersion = "1.0.0-SNAPSHOT" def internalPath = file("internal") @@ -25,11 +25,16 @@ def commonSettings: Seq[Setting[_]] = Seq( }, scalacOptions in console in Compile -= "-Ywarn-unused-import", scalacOptions in console in Test -= "-Ywarn-unused-import", - // mimaPreviousArtifacts := Set(), // Some(organization.value %% moduleName.value % "1.0.0"), publishArtifact in Compile := true, publishArtifact in Test := false ) +val mimaSettings = Def settings ( + mimaPreviousArtifacts := Set(organization.value % moduleName.value % "1.0.0-RC3" + cross (if (crossPaths.value) CrossVersion.binary else CrossVersion.disabled) + ) +) + lazy val utilRoot: Project = (project in file(".")). aggregate( utilInterface, utilControl, utilPosition, @@ -67,18 +72,21 @@ lazy val utilInterface = (project in internalPath / "util-interface"). commonSettings, javaOnlySettings, name := "Util Interface", - exportJars := true + exportJars := true, + mimaSettings, ) lazy val utilControl = (project in internalPath / "util-control"). settings( commonSettings, - name := "Util Control" + name := "Util Control", + mimaSettings, ) val utilPosition = (project in file("internal") / "util-position").settings( commonSettings, - name := "Util Position" + name := "Util Position", + mimaSettings, ) // logging @@ -97,6 +105,7 @@ lazy val utilLogging = (project in internalPath / "util-logging"). if (name == "Throwable") Nil else old(tpe) }, + mimaSettings, ) // Relation @@ -104,7 +113,8 @@ lazy val utilRelation = (project in internalPath / "util-relation"). dependsOn(utilTesting % Test). settings( commonSettings, - name := "Util Relation" + name := "Util Relation", + mimaSettings, ) // Persisted caching based on sjson-new @@ -113,7 +123,8 @@ lazy val utilCache = (project in file("util-cache")). settings( commonSettings, name := "Util Cache", - libraryDependencies ++= Seq(sjsonnewScalaJson.value, sjsonnewMurmurhash.value, scalaReflect.value) + libraryDependencies ++= Seq(sjsonnewScalaJson.value, sjsonnewMurmurhash.value, scalaReflect.value), + mimaSettings, ). configure(addSbtIO) @@ -122,7 +133,8 @@ lazy val utilTracking = (project in file("util-tracking")). dependsOn(utilCache, utilTesting % Test). settings( commonSettings, - name := "Util Tracking" + name := "Util Tracking", + mimaSettings, ). configure(addSbtIO) @@ -132,7 +144,8 @@ lazy val utilTesting = (project in internalPath / "util-testing"). commonSettings, crossScalaVersions := Seq(scala210, scala211, scala212), name := "Util Testing", - libraryDependencies ++= Seq(scalaCheck, scalatest) + libraryDependencies ++= Seq(scalaCheck, scalatest), + mimaSettings, ). configure(addSbtIO) @@ -147,7 +160,8 @@ lazy val utilScripted = (project in internalPath / "util-scripted"). case sv if sv startsWith "2.12" => Seq(parserCombinator211) case _ => Seq() } - } + }, + mimaSettings, ). configure(addSbtIO) diff --git a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/SuccessEvent.scala b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/SuccessEvent.scala new file mode 100644 index 000000000..9fdcc8e09 --- /dev/null +++ b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/SuccessEvent.scala @@ -0,0 +1,32 @@ +/** + * This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.util +final class SuccessEvent private ( + val message: String) extends Serializable { + + + + override def equals(o: Any): Boolean = o match { + case x: SuccessEvent => (this.message == x.message) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (17 + "sbt.internal.util.SuccessEvent".##) + message.##) + } + override def toString: String = { + "SuccessEvent(" + message + ")" + } + protected[this] def copy(message: String = message): SuccessEvent = { + new SuccessEvent(message) + } + def withMessage(message: String): SuccessEvent = { + copy(message = message) + } +} +object SuccessEvent { + + def apply(message: String): SuccessEvent = new SuccessEvent(message) +} diff --git a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/JsonProtocol.scala b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/JsonProtocol.scala index 4696c9612..a94906dda 100644 --- a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/JsonProtocol.scala +++ b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/JsonProtocol.scala @@ -8,4 +8,5 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol with sbt.internal.util.codec.StringEventFormats with sbt.internal.util.codec.TraceEventFormats with sbt.internal.util.codec.AbstractEntryFormats + with sbt.internal.util.codec.SuccessEventFormats object JsonProtocol extends JsonProtocol \ No newline at end of file diff --git a/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/SuccessEventFormats.scala b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/SuccessEventFormats.scala new file mode 100644 index 000000000..19621d7c1 --- /dev/null +++ b/internal/util-logging/src/main/contraband-scala/sbt/internal/util/codec/SuccessEventFormats.scala @@ -0,0 +1,27 @@ +/** + * This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.util.codec +import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } +trait SuccessEventFormats { self: sjsonnew.BasicJsonProtocol => +implicit lazy val SuccessEventFormat: JsonFormat[sbt.internal.util.SuccessEvent] = new JsonFormat[sbt.internal.util.SuccessEvent] { + override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.util.SuccessEvent = { + jsOpt match { + case Some(js) => + unbuilder.beginObject(js) + val message = unbuilder.readField[String]("message") + unbuilder.endObject() + sbt.internal.util.SuccessEvent(message) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.util.SuccessEvent, builder: Builder[J]): Unit = { + builder.beginObject() + builder.addField("message", obj.message) + builder.endObject() + } +} +} diff --git a/internal/util-logging/src/main/contraband/logging.contra b/internal/util-logging/src/main/contraband/logging.contra index 5cd31c230..19b019c66 100644 --- a/internal/util-logging/src/main/contraband/logging.contra +++ b/internal/util-logging/src/main/contraband/logging.contra @@ -21,3 +21,7 @@ type TraceEvent implements sbt.internal.util.AbstractEntry { channelName: String execId: String } + +type SuccessEvent { + message: String! +} diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/BufferedLogger.scala b/internal/util-logging/src/main/scala/sbt/internal/util/BufferedLogger.scala index be24152c1..93686c334 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/BufferedLogger.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/BufferedLogger.scala @@ -116,7 +116,9 @@ class BufferedLogger(delegate: AbstractLogger) extends BasicLogger { /** Plays buffered events and disables buffering. */ def stop(): Unit = synchronized { play(); clear() } + @deprecated("No longer used.", "1.0.0") override def ansiCodesSupported = delegate.ansiCodesSupported + override def setLevel(newLevel: Level.Value): Unit = synchronized { super.setLevel(newLevel) if (recording) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala b/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala index 422e420fb..ef392e785 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala @@ -1,6 +1,5 @@ package sbt.internal.util -import scala.compat.Platform.EOL import sbt.util._ import java.io.{ PrintStream, PrintWriter } import java.util.Locale @@ -269,11 +268,25 @@ class ConsoleAppender private[ConsoleAppender] ( useFormat: Boolean, suppressedMessage: SuppressedTraceContext => Option[String] ) extends AbstractAppender(name, null, LogExchange.dummyLayout, true) { - import scala.Console.{ BLUE, GREEN, RED, RESET, YELLOW } + import scala.Console.{ BLUE, GREEN, RED, YELLOW } - private final val SUCCESS_LABEL_COLOR = GREEN - private final val SUCCESS_MESSAGE_COLOR = RESET - private final val NO_COLOR = RESET + private val reset: String = { + if (ansiCodesSupported && useFormat) scala.Console.RESET + else "" + } + + private val SUCCESS_LABEL_COLOR = GREEN + private val SUCCESS_MESSAGE_COLOR = reset + private val NO_COLOR = reset + + private var traceEnabledVar: Int = Int.MaxValue + + def setTrace(level: Int): Unit = synchronized { traceEnabledVar = level } + + /** + * Returns the number of lines for stacktrace. + */ + def getTrace: Int = synchronized { traceEnabledVar } override def append(event: XLogEvent): Unit = { val level = ConsoleAppender.toLevel(event.getLevel) @@ -281,13 +294,6 @@ class ConsoleAppender private[ConsoleAppender] ( appendMessage(level, message) } - // TODO: - // success is called by ConsoleLogger. - // This should turn into an event. - private[sbt] def success(message: => String): Unit = { - appendLog(SUCCESS_LABEL_COLOR, Level.SuccessLabel, SUCCESS_MESSAGE_COLOR, message) - } - /** * Logs the stack trace of `t`, possibly shortening it. * @@ -333,7 +339,7 @@ class ConsoleAppender private[ConsoleAppender] ( * @return The formatted message. */ private def formatted(format: String, msg: String): String = - s"${RESET}${format}${msg}${RESET}" + s"$reset${format}${msg}$reset" /** * Select the right color for the label given `level`. @@ -362,41 +368,65 @@ class ConsoleAppender private[ConsoleAppender] ( private def appendLog(labelColor: String, label: String, messageColor: String, message: String): Unit = out.lockObject.synchronized { message.lines.foreach { line => - val labeledLine = s"$RESET[${formatted(labelColor, label)}] ${formatted(messageColor, line)}" + val labeledLine = s"$reset[${formatted(labelColor, label)}] ${formatted(messageColor, line)}" write(labeledLine) } } + // success is called by ConsoleLogger. + private[sbt] def success(message: => String): Unit = { + appendLog(SUCCESS_LABEL_COLOR, Level.SuccessLabel, SUCCESS_MESSAGE_COLOR, message) + } + private def write(msg: String): Unit = { val cleanedMsg = - if (!useFormat) EscHelpers.removeEscapeSequences(msg) + if (!useFormat || !ansiCodesSupported) EscHelpers.removeEscapeSequences(msg) else msg out.println(cleanedMsg) } private def appendMessage(level: Level.Value, msg: Message): Unit = msg match { - case o: ObjectMessage => objectToLines(o.getParameter) foreach { appendLog(level, _) } - case o: ReusableObjectMessage => objectToLines(o.getParameter) foreach { appendLog(level, _) } + case o: ObjectMessage => appendMessageContent(level, o.getParameter) + case o: ReusableObjectMessage => appendMessageContent(level, o.getParameter) case _ => appendLog(level, msg.getFormattedMessage) } - private def objectToLines(o: AnyRef): Vector[String] = + private def appendTraceEvent(te: TraceEvent): Unit = { + val traceLevel = getTrace + val throwableShowLines: ShowLines[Throwable] = + ShowLines[Throwable]( (t: Throwable) => { + List(StackTrace.trimmed(t, traceLevel)) + }) + val codec: ShowLines[TraceEvent] = + ShowLines[TraceEvent]( (t: TraceEvent) => { + throwableShowLines.showLines(t.message) + }) + codec.showLines(te).toVector foreach { appendLog(Level.Error, _) } + } + + private def appendMessageContent(level: Level.Value, o: AnyRef): Unit = { + def appendEvent(oe: ObjectEvent[_]): Unit = + { + val contentType = oe.contentType + if (contentType == "sbt.internal.util.TraceEvent") { + appendTraceEvent(oe.message.asInstanceOf[TraceEvent]) + } + else LogExchange.stringCodec[AnyRef](contentType) match { + case Some(codec) if contentType == "sbt.internal.util.SuccessEvent" => + codec.showLines(oe.message.asInstanceOf[AnyRef]).toVector foreach { success(_) } + case Some(codec) => + codec.showLines(oe.message.asInstanceOf[AnyRef]).toVector foreach { appendLog(level, _) } + case _ => appendLog(level, oe.message.toString) + } + } + o match { - case x: StringEvent => Vector(x.message) - case x: ObjectEvent[_] => objectEventToLines(x) - case _ => Vector(o.toString) + case x: StringEvent => Vector(x.message) foreach { appendLog(level, _) } + case x: ObjectEvent[_] => appendEvent(x) + case _ => Vector(o.toString) foreach { appendLog(level, _) } } - - private def objectEventToLines(oe: ObjectEvent[_]): Vector[String] = - { - val contentType = oe.contentType - LogExchange.stringCodec[AnyRef](contentType) match { - case Some(codec) => codec.showLines(oe.message.asInstanceOf[AnyRef]).toVector - case _ => Vector(oe.message.toString) - } - } - + } } final class SuppressedTraceContext(val traceLevel: Int, val useFormat: Boolean) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/FullLogger.scala b/internal/util-logging/src/main/scala/sbt/internal/util/FullLogger.scala index 1493e2d0f..c3ad40442 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/FullLogger.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/FullLogger.scala @@ -7,7 +7,9 @@ import sbt.util._ /** Promotes the simple Logger interface to the full AbstractLogger interface. */ class FullLogger(delegate: Logger) extends BasicLogger { + @deprecated("No longer used.", "1.0.0") override val ansiCodesSupported: Boolean = delegate.ansiCodesSupported + def trace(t: => Throwable): Unit = { if (traceEnabled) delegate.trace(t) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/ManagedLogger.scala b/internal/util-logging/src/main/scala/sbt/internal/util/ManagedLogger.scala index 794107111..5a9215ba8 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/ManagedLogger.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/ManagedLogger.scala @@ -7,6 +7,7 @@ import sjsonnew.JsonFormat import scala.reflect.runtime.universe.TypeTag import sbt.internal.util.codec.ThrowableShowLines._ import sbt.internal.util.codec.TraceEventShowLines._ +import sbt.internal.util.codec.SuccessEventShowLines._ import sbt.internal.util.codec.JsonProtocol._ /** @@ -27,7 +28,11 @@ class ManagedLogger( new ObjectMessage(StringEvent(level.toString, message, channelName, execId)) ) } - override def success(message: => String): Unit = xlogger.info(message) + + // send special event for success since it's not a real log level + override def success(message: => String): Unit = { + infoEvent[SuccessEvent](SuccessEvent(message)) + } def registerStringCodec[A: ShowLines: TypeTag]: Unit = { @@ -38,6 +43,7 @@ class ManagedLogger( } registerStringCodec[Throwable] registerStringCodec[TraceEvent] + registerStringCodec[SuccessEvent] final def debugEvent[A: JsonFormat: TypeTag](event: => A): Unit = logEvent(Level.Debug, event) final def infoEvent[A: JsonFormat: TypeTag](event: => A): Unit = logEvent(Level.Info, event) final def warnEvent[A: JsonFormat: TypeTag](event: => A): Unit = logEvent(Level.Warn, event) @@ -54,4 +60,7 @@ class ManagedLogger( new ObjectMessage(entry) ) } + + @deprecated("No longer used.", "1.0.0") + override def ansiCodesSupported = ConsoleAppender.formatEnabledInEnv } diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/MultiLogger.scala b/internal/util-logging/src/main/scala/sbt/internal/util/MultiLogger.scala index c72d094af..ef82fa10f 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/MultiLogger.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/MultiLogger.scala @@ -9,8 +9,8 @@ import sbt.util._ // note that setting the logging level on this logger has no effect on its behavior, only // on the behavior of the delegates. class MultiLogger(delegates: List[AbstractLogger]) extends BasicLogger { + @deprecated("No longer used.", "1.0.0") override lazy val ansiCodesSupported = delegates exists supported - private[this] lazy val allSupportCodes = delegates forall supported private[this] def supported = (_: AbstractLogger).ansiCodesSupported override def setLevel(newLevel: Level.Value): Unit = { @@ -31,22 +31,8 @@ class MultiLogger(delegates: List[AbstractLogger]) extends BasicLogger { def logAll(events: Seq[LogEvent]): Unit = delegates.foreach(_.logAll(events)) def control(event: ControlEvent.Value, message: => String): Unit = delegates.foreach(_.control(event, message)) private[this] def dispatch(event: LogEvent): Unit = { - val plainEvent = if (allSupportCodes) event else removeEscapes(event) - for (d <- delegates) - if (d.ansiCodesSupported) - d.log(event) - else - d.log(plainEvent) - } - - private[this] def removeEscapes(event: LogEvent): LogEvent = - { - import EscHelpers.{ removeEscapeSequences => rm } - event match { - case s: Success => new Success(rm(s.msg)) - case l: Log => new Log(l.level, rm(l.msg)) - case ce: ControlEvent => new ControlEvent(ce.event, rm(ce.msg)) - case _: Trace | _: SetLevel | _: SetTrace | _: SetSuccess => event - } + for (d <- delegates) { + d.log(event) } + } } diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/StackTrace.scala b/internal/util-logging/src/main/scala/sbt/internal/util/StackTrace.scala index e636d914c..20821eefb 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/StackTrace.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/StackTrace.scala @@ -9,12 +9,13 @@ object StackTrace { * Return a printable representation of the stack trace associated * with t. Information about t and its Throwable causes is included. * The number of lines to be included for each Throwable is configured - * via d which should be greater than or equal to zero. If d is zero, - * then all elements are included up to (but not including) the first - * element that comes from sbt. If d is greater than zero, then up to - * that many lines are included, where the line for the Throwable is - * counted plus one line for each stack element. Less lines will be - * included if there are not enough stack elements. + * via d which should be greater than or equal to 0. + * + * - If d is 0, then all elements are included up to (but not including) + * the first element that comes from sbt. + * - If d is greater than 0, then up to that many lines are included, + * where the line for the Throwable is counted plus one line for each stack element. + * Less lines will be included if there are not enough stack elements. */ def trimmed(t: Throwable, d: Int): String = { require(d >= 0) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/codec/SuccessEventShowLines.scala b/internal/util-logging/src/main/scala/sbt/internal/util/codec/SuccessEventShowLines.scala new file mode 100644 index 000000000..e3b338719 --- /dev/null +++ b/internal/util-logging/src/main/scala/sbt/internal/util/codec/SuccessEventShowLines.scala @@ -0,0 +1,14 @@ +package sbt +package internal.util.codec + +import sbt.util.ShowLines +import sbt.internal.util.SuccessEvent + +trait SuccessEventShowLines { + implicit val sbtSuccessEventShowLines: ShowLines[SuccessEvent] = + ShowLines[SuccessEvent]( (e: SuccessEvent) => { + Vector(e.message) + }) +} + +object SuccessEventShowLines extends SuccessEventShowLines diff --git a/internal/util-logging/src/main/scala/sbt/util/Logger.scala b/internal/util-logging/src/main/scala/sbt/util/Logger.scala index abcad3428..0bcea3b78 100644 --- a/internal/util-logging/src/main/scala/sbt/util/Logger.scala +++ b/internal/util-logging/src/main/scala/sbt/util/Logger.scala @@ -27,6 +27,7 @@ abstract class Logger extends xLogger { // sys.process.ProcessLogger final def out(message: => String): Unit = log(Level.Info, message) + @deprecated("No longer used.", "1.0.0") def ansiCodesSupported: Boolean = false def trace(t: => Throwable): Unit diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 076545c47..73e3a8304 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -5,9 +5,9 @@ import sbt.contraband.ContrabandPlugin.autoImport._ object Dependencies { val scala210 = "2.10.6" val scala211 = "2.11.11" - val scala212 = "2.12.2" + val scala212 = "2.12.3" - private val ioVersion = "1.0.0-M13" + private val ioVersion = "1.0.0" private val sbtIO = "org.scala-sbt" %% "io" % ioVersion @@ -51,6 +51,5 @@ object Dependencies { def log4jVersion = "2.8.1" val log4jApi = "org.apache.logging.log4j" % "log4j-api" % log4jVersion val log4jCore = "org.apache.logging.log4j" % "log4j-core" % log4jVersion - val log4jSlf4jImpl = "org.apache.logging.log4j" % "log4j-slf4j-impl" % log4jVersion val disruptor = "com.lmax" % "disruptor" % "3.3.6" } diff --git a/project/build.properties b/project/build.properties index cd66fd542..12c38d389 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.0.0-M6 +sbt.version=1.0.0-RC3 diff --git a/project/plugins.sbt b/project/plugins.sbt index 9e3900c5b..493521644 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,6 +1,3 @@ -addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.4.0") -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0-M1") addSbtPlugin("org.scala-sbt" % "sbt-houserules" % "0.3.3") -addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.0-M9") - -resolvers += Resolver.sonatypeRepo("public") +addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.0") +addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.17")