Merge branch '1.0.x' into topic/generators

This commit is contained in:
eugene yokota 2017-02-06 16:17:21 -05:00 committed by GitHub
commit ba28c00a1a
14 changed files with 130 additions and 55 deletions

View File

@ -12,6 +12,7 @@ Migration notes
- Removes no-longer-documented old operators `<<=`, `<+=`, and `<++=`.
- Renames early command feature from `--<command>` to `early(<command>)`.
- Log options `-error`, `-warn`, `-info`, `-debug` are added as shorthand for `"early(error)"` etc.
- `sbt.Process` and `sbt.ProcessExtra` are gone. Use `scala.sys.process` instead.
#### Additional import required

View File

@ -155,6 +155,7 @@ object Defaults extends BuildCommon {
retrieveManagedSync :== false,
configurationsToRetrieve :== None,
scalaOrganization :== ScalaArtifacts.Organization,
scalaArtifacts :== ScalaArtifacts.Artifacts,
sbtResolver := { if (sbtVersion.value endsWith "-SNAPSHOT") Classpaths.sbtIvySnapshots else Classpaths.typesafeReleases },
crossVersion :== Disabled(),
buildDependencies := Classpaths.constructBuildDependencies.value,
@ -368,7 +369,8 @@ object Defaults extends BuildCommon {
private[this] lazy val configGlobal = globalDefaults(Seq(
initialCommands :== "",
cleanupCommands :== ""
cleanupCommands :== "",
asciiGraphWidth :== 40
))
lazy val projectTasks: Seq[Setting[_]] = Seq(
@ -1431,7 +1433,9 @@ object Classpaths {
(scalaVersion in update).value,
(scalaBinaryVersion in update).value,
Vector.empty, filterImplicit = false, checkExplicit = true, overrideScalaVersion = true
).withScalaOrganization(scalaOrganization.value))
)
.withScalaOrganization(scalaOrganization.value)
.withScalaArtifacts(scalaArtifacts.value.toVector))
}
)).value,
artifactPath in makePom := artifactPathSetting(artifact in makePom).value,

View File

@ -150,8 +150,15 @@ object EvaluateTask {
import std.Transform
import Keys.state
lazy private val sharedProgress = new TaskTimings(shutdown = true)
private[sbt] def defaultProgress: ExecuteProgress[Task] =
if (java.lang.Boolean.getBoolean("sbt.task.timings")) new TaskTimings else ExecuteProgress.empty[Task]
if (java.lang.Boolean.getBoolean("sbt.task.timings")) {
if (java.lang.Boolean.getBoolean("sbt.task.timings.on.shutdown"))
sharedProgress
else
new TaskTimings(shutdown = false)
} else ExecuteProgress.empty[Task]
val SystemProcessors = Runtime.getRuntime.availableProcessors

View File

@ -179,6 +179,7 @@ object Keys {
val compileOrder = SettingKey[CompileOrder]("compile-order", "Configures the order in which Java and sources within a single compilation are compiled. Valid values are: JavaThenScala, ScalaThenJava, or Mixed.", BPlusSetting)
val initialCommands = SettingKey[String]("initial-commands", "Initial commands to execute when starting up the Scala interpreter.", AMinusSetting)
val cleanupCommands = SettingKey[String]("cleanup-commands", "Commands to execute before the Scala interpreter exits.", BMinusSetting)
val asciiGraphWidth = SettingKey[Int]("asciiGraphWidth", "Determines maximum width of the settings graph in ASCII mode", AMinusSetting)
val compileOptions = TaskKey[CompileOptions]("compile-options", "Collects basic options to configure compilers", DTask)
val compileInputs = TaskKey[Inputs]("compile-inputs", "Collects all inputs needed for compilation.", DTask)
val scalaHome = SettingKey[Option[File]]("scala-home", "If Some, defines the local Scala installation to use for compilation, running, and testing.", ASetting)
@ -194,6 +195,7 @@ object Keys {
val printWarnings = TaskKey[Unit]("print-warnings", "Shows warnings from compilation, including ones that weren't printed initially.", BPlusTask)
val fileInputOptions = SettingKey[Seq[String]]("file-input-options", "Options that take file input, which may invalidate the cache.", CSetting)
val scalaCompilerBridgeSource = SettingKey[ModuleID]("scala-compiler-bridge-source", "Configures the module ID of the sources of the compiler bridge.", CSetting)
val scalaArtifacts = SettingKey[Seq[String]]("scala-artifacts", "Configures the list of artifacts which should match the Scala binary version", CSetting)
val clean = TaskKey[Unit]("clean", "Deletes files produced by the build, such as generated sources, compiled classes, and task caches.", APlusTask)
val console = TaskKey[Unit]("console", "Starts the Scala interpreter with the project classes on the classpath.", APlusTask)

View File

@ -27,7 +27,7 @@ import sbt.internal.{
import sbt.internal.util.{ AttributeKey, AttributeMap, complete, ConsoleOut, GlobalLogging, LineRange, MainAppender, SimpleReader, Types }
import sbt.util.{ Level, Logger }
import complete.{ DefaultParsers, Parser }
import sbt.internal.util.complete.{ DefaultParsers, Parser }
import sbt.internal.inc.{ CompilerCache, ScalaInstance }
import sbt.compiler.EvalImports
import Types.{ const, idFun }
@ -221,7 +221,7 @@ object BuiltinCommands {
Some(index.keyMap(key))
catch {
case NonFatal(ex) =>
s.log error ex.getMessage
s.log debug ex.getMessage
None
}
}.collect { case Some(s) => s }.distinct
@ -356,7 +356,7 @@ object BuiltinCommands {
val extracted = Project extract s
import extracted.{ showKey, structure }
val keysParser = token(flag("--last" <~ Space)) ~ Act.aggregatedKeyParser(extracted)
val show = Aggregation.ShowConfig(settingValues = true, taskValues = false, print = println _, success = false)
val show = Aggregation.ShowConfig(settingValues = true, taskValues = false, print = println(_), success = false)
for {
lastOnly_keys <- keysParser
kvs = Act.keyValues(structure)(lastOnly_keys._2)

View File

@ -47,7 +47,7 @@ object Inspect {
Project.details(structure, actual, sk.scope, sk.key)
case DependencyTreeMode =>
val basedir = new File(Project.session(s).current.build)
Project.settingGraph(structure, basedir, sk).dependsAscii
Project.settingGraph(structure, basedir, sk).dependsAscii(get(sbt.Keys.asciiGraphWidth))
case UsesMode =>
Project.showUses(Project.usedBy(structure, true, sk.key))
case DefinitionsMode =>

View File

@ -4,7 +4,7 @@
package sbt
package internal
import sbt.internal.util.Show
import sbt.internal.util.{ Show, JLine }
import java.io.File
import Def.{ compiled, flattenLocals, ScopedKey }
@ -50,10 +50,11 @@ case class SettingGraph(
} getOrElse { d.typeName }
} getOrElse { "" }
def dependsAscii: String = Graph.toAscii(
def dependsAscii(defaultWidth: Int): String = Graph.toAscii(
this,
(x: SettingGraph) => x.depends.toSeq.sortBy(_.name),
(x: SettingGraph) => "%s = %s" format (x.definedIn getOrElse { "" }, x.dataString)
(x: SettingGraph) => "%s = %s" format (x.definedIn getOrElse { "" }, x.dataString),
defaultWidth
)
}
@ -63,10 +64,8 @@ object Graph {
// [info] | +-baz
// [info] |
// [info] +-quux
def toAscii[A](top: A, children: A => Seq[A], display: A => String): String = {
val defaultWidth = 40
// TODO: Fix JLine
val maxColumn = math.max( /*JLine.usingTerminal(_.getWidth)*/ 0, defaultWidth) - 8
def toAscii[A](top: A, children: A => Seq[A], display: A => String, defaultWidth: Int): String = {
val maxColumn = math.max(JLine.usingTerminal(_.getWidth), defaultWidth) - 8
val twoSpaces = " " + " " // prevent accidentally being converted into a tab
def limitLine(s: String): String =
if (s.length > maxColumn) s.slice(0, maxColumn - 2) + ".."

View File

@ -6,15 +6,45 @@ import sbt.internal.util.RMap
import java.util.concurrent.ConcurrentHashMap
import TaskName._
private[sbt] final class TaskTimings extends ExecuteProgress[Task] {
/**
* Measure the time elapsed for running tasks.
* This class is activated by adding -Dsbt.task.timing=true to the JVM options.
* Formatting options:
* - -Dsbt.task.timings.on.shutdown=true|false
* - -Dsbt.task.timings.unit=number
* - -Dsbt.task.timings.threshold=number
* @param shutdown Should the report be given when exiting the JVM (true) or immediatelly (false)?
*/
private[sbt] final class TaskTimings(shutdown: Boolean) extends ExecuteProgress[Task] {
private[this] val calledBy = new ConcurrentHashMap[Task[_], Task[_]]
private[this] val anonOwners = new ConcurrentHashMap[Task[_], Task[_]]
private[this] val timings = new ConcurrentHashMap[Task[_], Long]
private[this] var start = 0L
private[this] val threshold = java.lang.Long.getLong("sbt.task.timings.threshold", 0L)
private[this] val omitPaths = java.lang.Boolean.getBoolean("sbt.task.timings.omit.paths")
private[this] val (unit, divider) = System.getProperty("sbt.task.timings.unit", "ms") match {
case "ns" => ("ns", 0)
case "us" => ("µs", 3)
case "ms" => ("ms", 6)
case "s" => ("sec", 9)
case x =>
System.err.println(s"Unknown sbt.task.timings.unit: $x.\nUsing milliseconds.")
("ms", 6)
}
type S = Unit
def initial = { start = System.nanoTime }
if (shutdown) {
start = System.nanoTime
Runtime.getRuntime.addShutdownHook(new Thread {
override def run() = report()
})
}
def initial = {
if (!shutdown)
start = System.nanoTime
}
def registered(state: Unit, task: Task[_], allDeps: Iterable[Task[_]], pendingDeps: Iterable[Task[_]]) = {
pendingDeps foreach { t => if (transformNode(t).isEmpty) anonOwners.put(t, task) }
}
@ -26,16 +56,34 @@ private[sbt] final class TaskTimings extends ExecuteProgress[Task] {
}
def completed[T](state: Unit, task: Task[T], result: Result[T]) = ()
def allCompleted(state: Unit, results: RMap[Task, Result]) =
{
val total = System.nanoTime - start
println("Total time: " + (total * 1e-6) + " ms")
import collection.JavaConverters._
def sumTimes(in: Seq[(Task[_], Long)]) = in.map(_._2).sum
val timingsByName = timings.asScala.toSeq.groupBy { case (t, time) => mappedName(t) } mapValues (sumTimes)
for ((taskName, time) <- timingsByName.toSeq.sortBy(_._2).reverse)
println(" " + taskName + ": " + (time * 1e-6) + " ms")
if (!shutdown) {
report()
}
private val reFilePath = raw"\{[^}]+\}".r
private[this] def report() = {
val total = divide(System.nanoTime - start)
println(s"Total time: $total $unit")
import collection.JavaConverters._
def sumTimes(in: Seq[(Task[_], Long)]) = in.map(_._2).sum
val timingsByName = timings.asScala.toSeq.groupBy { case (t, time) => mappedName(t) } mapValues (sumTimes)
val times = timingsByName.toSeq.sortBy(_._2).reverse
.map {
case (name, time) =>
(if (omitPaths) reFilePath.replaceFirstIn(name, "") else name, divide(time))
}.filter { _._2 > threshold }
if (times.size > 0) {
val maxTaskNameLength = times.map { _._1.length }.max
val maxTime = times.map { _._2 }.max.toString.length
times.foreach {
case (taskName, time) =>
println(s" ${taskName.padTo(maxTaskNameLength, ' ')}: ${"".padTo(maxTime - time.toString.length, ' ')}$time $unit")
}
}
}
private[this] def inferredName(t: Task[_]): Option[String] = nameDelegate(t) map mappedName
private[this] def nameDelegate(t: Task[_]): Option[Task[_]] = Option(anonOwners.get(t)) orElse Option(calledBy.get(t))
private[this] def mappedName(t: Task[_]): String = definedName(t) orElse inferredName(t) getOrElse anonymousName(t)
private[this] def divide(time: Long) = (1L to divider.toLong).fold(time) { (a, b) => a / 10L }
}

View File

@ -0,0 +1,9 @@
[@RomanIakovlev]: https://github.com/RomanIakovlev
### Fixes with compatibility implications
### Improvements
Add new global setting `asciiGraphWidth` that controls the maximum width of the ASCII graphs printed by commands like `inspect tree`. Default value corresponds to the previously hardcoded value of 40 characters. By [@RomanIakovlev][@RomanIakovlev].
### Bug fixes

View File

@ -46,8 +46,6 @@ case class LoggedOutput(logger: Logger) extends OutputStrategy
*/
case class CustomOutput(output: OutputStream) extends OutputStrategy
import java.lang.{ ProcessBuilder => JProcessBuilder }
/**
* Represents a command that can be forked.
*
@ -75,20 +73,16 @@ final class Fork(val commandName: String, val runnerClass: Option[String]) {
val executable = Fork.javaCommand(javaHome, commandName).getAbsolutePath
val preOptions = makeOptions(runJVMOptions, bootJars, arguments)
val (classpathEnv, options) = Fork.fitClasspath(preOptions)
val command = (executable +: options).toArray
val builder = new JProcessBuilder(command: _*)
workingDirectory.foreach(wd => builder.directory(wd))
val environment = builder.environment
for ((key, value) <- env)
environment.put(key, value)
for (cpenv <- classpathEnv)
// overriding, not appending, is correct due to the specified priorities of -classpath and CLASSPATH
environment.put(Fork.ClasspathEnvKey, cpenv)
val command = executable +: options
val environment = env ++ classpathEnv.map(value => Fork.ClasspathEnvKey -> value)
val process = Process(command, workingDirectory, environment.toList: _*)
outputStrategy.getOrElse(StdoutOutput) match {
case StdoutOutput => Process(builder).run(connectInput)
case BufferedOutput(logger) => logger.buffer { Process(builder).run(logger, connectInput) }
case LoggedOutput(logger) => Process(builder).run(logger, connectInput)
case CustomOutput(output) => (Process(builder) #> output).run(connectInput)
case StdoutOutput => process.run(connectInput)
case BufferedOutput(logger) => logger.buffer { process.run(logger, connectInput) }
case LoggedOutput(logger) => process.run(logger, connectInput)
case CustomOutput(output) => (process #> output).run(connectInput)
}
}
private[this] def makeOptions(jvmOptions: Seq[String], bootJars: Iterable[File], arguments: Seq[String]): Seq[String] =

View File

@ -1,15 +0,0 @@
package sbt
import java.lang.{ ProcessBuilder => JProcessBuilder }
trait ProcessExtra {
import scala.sys.process._
import scala.sys.process.Process._
implicit def builderToProcess(builder: JProcessBuilder): ProcessBuilder = apply(builder)
implicit def fileToProcess(file: File): ProcessBuilder.FileBuilder = apply(file)
implicit def urlToProcess(url: URL): ProcessBuilder.URLBuilder = apply(url)
implicit def buildersToProcess[T](builders: Seq[T])(implicit convert: T => ProcessBuilder.Source): Seq[ProcessBuilder.Source] = applySeq(builders)
implicit def stringToProcess(command: String): ProcessBuilder = apply(command)
implicit def stringSeqToProcess(command: Seq[String]): ProcessBuilder = apply(command)
}

View File

@ -2,7 +2,7 @@ package sbt
object syntax extends syntax
abstract class syntax extends IOSyntax0 with sbt.std.TaskExtra with sbt.internal.util.Types with sbt.ProcessExtra
abstract class syntax extends IOSyntax0 with sbt.std.TaskExtra with sbt.internal.util.Types
with sbt.internal.librarymanagement.impl.DependencyBuilders with sbt.ProjectExtra
with sbt.internal.librarymanagement.DependencyFilterExtra with sbt.BuildExtra with sbt.TaskMacroExtra
with sbt.ScopeFilter.Make

View File

@ -0,0 +1,23 @@
scalaOrganization := "org.other"
scalaArtifacts += "thing"
scalaVersion := "2.11.8"
libraryDependencies ++= Seq(
"org.other" % "thing" % "1.2.3",
"org.other" %% "wotsit" % "4.5.6"
)
lazy val check = taskKey[Unit]("Runs the check")
check := {
val lastLog = BuiltinCommands lastLogFile state.value
val last = IO read lastLog.get
def containsWarn1 = last contains "Binary version (1.2.3) for dependency org.other#thing;1.2.3"
def containsWarn2 = last contains "Binary version (4.5.6) for dependency org.other#wotsit_2.11;4.5.6"
def containsWarn3 = last contains "differs from Scala binary version in project (2.11)."
if (!containsWarn1) sys error "thing should not be exempted from the Scala binary version check"
if (containsWarn2) sys error "wotsit should be exempted from the Scala binary version check"
if (!containsWarn3) sys error "Binary version check failed"
}

View File

@ -0,0 +1,3 @@
> clean
> check