Merge pull request #3483 from sbt/1.0.x

Merge 1.0.1 to 1.x
This commit is contained in:
eugene yokota 2017-08-31 13:04:57 -04:00 committed by GitHub
commit 34945af631
20 changed files with 276 additions and 80 deletions

View File

@ -26,7 +26,9 @@ env:
- SBT_CMD="scripted java/* package/* reporter/* run/* project-load/*" - SBT_CMD="scripted java/* package/* reporter/* run/* project-load/*"
- SBT_CMD="scripted project/*1of2" - SBT_CMD="scripted project/*1of2"
- SBT_CMD="scripted project/*2of2" - SBT_CMD="scripted project/*2of2"
- SBT_CMD="scripted source-dependencies/*" - SBT_CMD="scripted source-dependencies/*1of3"
- SBT_CMD="scripted source-dependencies/*2of3"
- SBT_CMD="scripted source-dependencies/*3of3"
- SBT_CMD="scripted tests/*" - SBT_CMD="scripted tests/*"
- SBT_CMD="repoOverrideTest:scripted dependency-management/*" - SBT_CMD="repoOverrideTest:scripted dependency-management/*"

View File

@ -1,6 +1,7 @@
import Util._ import Util._
import Dependencies._ import Dependencies._
import Sxr.sxr import Sxr.sxr
import com.typesafe.tools.mima.core._, ProblemFilters._
// ThisBuild settings take lower precedence, // ThisBuild settings take lower precedence,
// but can be shared across the multi projects. // but can be shared across the multi projects.
@ -66,7 +67,7 @@ def testedBaseSettings: Seq[Setting[_]] =
val mimaSettings = Def settings ( val mimaSettings = Def settings (
mimaPreviousArtifacts := Set( mimaPreviousArtifacts := Set(
organization.value % moduleName.value % "1.0.0-RC3" organization.value % moduleName.value % "1.0.0"
cross (if (crossPaths.value) CrossVersion.binary else CrossVersion.disabled) cross (if (crossPaths.value) CrossVersion.binary else CrossVersion.disabled)
) )
) )
@ -382,9 +383,18 @@ lazy val sbtProj = (project in file("sbt"))
crossScalaVersions := Seq(baseScalaVersion), crossScalaVersions := Seq(baseScalaVersion),
crossPaths := false, crossPaths := false,
mimaSettings, mimaSettings,
mimaBinaryIssueFilters ++= sbtIgnoredProblems,
) )
.configure(addSbtCompilerBridge) .configure(addSbtCompilerBridge)
lazy val sbtIgnoredProblems = {
Seq(
// Added more items to Import trait.
exclude[ReversedMissingMethodProblem]("sbt.Import.sbt$Import$_setter_$WatchSource_="),
exclude[ReversedMissingMethodProblem]("sbt.Import.WatchSource")
)
}
def scriptedTask: Def.Initialize[InputTask[Unit]] = Def.inputTask { def scriptedTask: Def.Initialize[InputTask[Unit]] = Def.inputTask {
val result = scriptedSource(dir => (s: State) => Scripted.scriptedParser(dir)).parsed val result = scriptedSource(dir => (s: State) => Scripted.scriptedParser(dir)).parsed
// publishLocalBinAll.value // TODO: Restore scripted needing only binary jars. // publishLocalBinAll.value // TODO: Restore scripted needing only binary jars.

View File

@ -6,11 +6,12 @@ package sbt
import BasicCommandStrings.ClearOnFailure import BasicCommandStrings.ClearOnFailure
import State.FailureWall import State.FailureWall
import annotation.tailrec import annotation.tailrec
import java.io.File
import java.nio.file.FileSystems import java.nio.file.FileSystems
import scala.concurrent.duration._ import scala.concurrent.duration._
import sbt.io.WatchService import sbt.io.{ AllPassFilter, NothingFilter, FileFilter, WatchService }
import sbt.internal.io.{ Source, SourceModificationWatch, WatchState } import sbt.internal.io.{ Source, SourceModificationWatch, WatchState }
import sbt.internal.util.AttributeKey import sbt.internal.util.AttributeKey
import sbt.internal.util.Types.const import sbt.internal.util.Types.const
@ -18,7 +19,7 @@ import sbt.internal.util.Types.const
trait Watched { trait Watched {
/** The files watched when an action is run with a preceeding ~ */ /** The files watched when an action is run with a preceeding ~ */
def watchSources(s: State): Seq[Source] = Nil def watchSources(s: State): Seq[Watched.WatchSource] = Nil
def terminateWatch(key: Int): Boolean = Watched.isEnter(key) def terminateWatch(key: Int): Boolean = Watched.isEnter(key)
/** /**
@ -44,6 +45,30 @@ object Watched {
val clearWhenTriggered: WatchState => String = const(clearScreen) val clearWhenTriggered: WatchState => String = const(clearScreen)
def clearScreen: String = "\u001b[2J\u001b[0;0H" def clearScreen: String = "\u001b[2J\u001b[0;0H"
type WatchSource = Source
object WatchSource {
/**
* Creates a new `WatchSource` for watching files, with the given filters.
*
* @param base The base directory from which to include files.
* @param includeFilter Choose what children of `base` to include.
* @param excludeFilter Choose what children of `base` to exclude.
* @return An instance of `Source`.
*/
def apply(base: File, includeFilter: FileFilter, excludeFilter: FileFilter): Source =
new Source(base, includeFilter, excludeFilter)
/**
* Creates a new `WatchSource` for watching files.
*
* @param base The base directory from which to include files.
* @return An instance of `Source`.
*/
def apply(base: File): Source =
apply(base, AllPassFilter, NothingFilter)
}
private[this] class AWatched extends Watched private[this] class AWatched extends Watched
def multi(base: Watched, paths: Seq[Watched]): Watched = def multi(base: Watched, paths: Seq[Watched]): Watched =

View File

@ -6,6 +6,8 @@ import scala.annotation.implicitNotFound
import sbt.internal.util.Attributed import sbt.internal.util.Attributed
import Def.Initialize import Def.Initialize
import reflect.internal.annotations.compileTimeOnly import reflect.internal.annotations.compileTimeOnly
import sbt.internal.io.Source
import sbt.io.{ AllPassFilter, NothingFilter }
object Append { object Append {
@implicitNotFound( @implicitNotFound(
@ -96,4 +98,11 @@ object Append {
def appendValue(a: Seq[T], b: Option[T]): Seq[T] = b.fold(a)(a :+ _) def appendValue(a: Seq[T], b: Option[T]): Seq[T] = b.fold(a)(a :+ _)
def appendValues(a: Seq[T], b: Option[T]): Seq[T] = b.fold(a)(a :+ _) def appendValues(a: Seq[T], b: Option[T]): Seq[T] = b.fold(a)(a :+ _)
} }
implicit def appendSource: Sequence[Seq[Source], Seq[File], File] =
new Sequence[Seq[Source], Seq[File], File] {
def appendValue(a: Seq[Source], b: File): Seq[Source] =
appendValues(a, Seq(b))
def appendValues(a: Seq[Source], b: Seq[File]): Seq[Source] =
a ++ b.map(new Source(_, AllPassFilter, NothingFilter))
}
} }

View File

@ -5,6 +5,7 @@ import sbt.util.Logger
import Def.{ ScopedKey, Classpath } import Def.{ ScopedKey, Classpath }
import sbt.internal.util.complete._ import sbt.internal.util.complete._
import java.io.File import java.io.File
import scala.util.Try
abstract class BackgroundJobService extends Closeable { abstract class BackgroundJobService extends Closeable {
@ -24,6 +25,12 @@ abstract class BackgroundJobService extends Closeable {
def shutdown(): Unit def shutdown(): Unit
def jobs: Vector[JobHandle] def jobs: Vector[JobHandle]
def stop(job: JobHandle): Unit def stop(job: JobHandle): Unit
def waitForTry(job: JobHandle): Try[Unit] = {
// This implementation is provided only for backward compatibility.
Try(waitFor(job))
}
def waitFor(job: JobHandle): Unit def waitFor(job: JobHandle): Unit
/** Copies classpath to temporary directories. */ /** Copies classpath to temporary directories. */

View File

@ -3,7 +3,7 @@
*/ */
package sbt package sbt
import Keys._ import Keys.{ version, _ }
import sbt.internal.util.complete.{ DefaultParsers, Parser } import sbt.internal.util.complete.{ DefaultParsers, Parser }
import sbt.internal.util.AttributeKey import sbt.internal.util.AttributeKey
import DefaultParsers._ import DefaultParsers._
@ -18,6 +18,7 @@ import sbt.internal.CommandStrings.{
} }
import java.io.File import java.io.File
import sbt.internal.Act
import sbt.internal.inc.ScalaInstance import sbt.internal.inc.ScalaInstance
import sbt.io.IO import sbt.io.IO
import sbt.librarymanagement.CrossVersion import sbt.librarymanagement.CrossVersion
@ -125,10 +126,13 @@ object Cross {
case Left(cmd) => (resolveAggregates(x), cmd) case Left(cmd) => (resolveAggregates(x), cmd)
} }
val projCrossVersions = aggs map { proj =>
proj -> crossVersions(x, proj)
}
// if we support scalaVersion, projVersions should be cached somewhere since // if we support scalaVersion, projVersions should be cached somewhere since
// running ++2.11.1 is at the root level is going to mess with the scalaVersion for the aggregated subproj // running ++2.11.1 is at the root level is going to mess with the scalaVersion for the aggregated subproj
val projVersions = (aggs flatMap { proj => val projVersions = (projCrossVersions flatMap {
crossVersions(x, proj) map { (proj.project, _) } case (proj, versions) => versions map { proj.project -> _ }
}).toList }).toList
val verbose = if (args.verbose) "-v" else "" val verbose = if (args.verbose) "-v" else ""
@ -136,19 +140,51 @@ object Cross {
if (projVersions.isEmpty) { if (projVersions.isEmpty) {
state state
} else { } else {
// Group all the projects by scala version // Detect whether a task or command has been issued
val allCommands = projVersions.groupBy(_._2).mapValues(_.map(_._1)).toSeq.flatMap { val allCommands = Parser.parse(aggCommand, Act.aggregatedKeyParser(x)) match {
case (version, Seq(project)) => case Left(_) =>
// If only one project for a version, issue it directly // It's definitely not a task, check if it's a valid command, because we don't want to emit the warning
Seq(s"$SwitchCommand $verbose $version $project/$aggCommand") // message below for typos.
case (version, projects) if aggCommand.contains(" ") => val validCommand = Parser.parse(aggCommand, state.combinedParser).isRight
// If the command contains a space, then the all command won't work because it doesn't support issuing
// commands with spaces, so revert to running the command on each project one at a time val distinctCrossConfigs = projCrossVersions.map(_._2.toSet).distinct
s"$SwitchCommand $verbose $version" :: projects.map(project => s"$project/$aggCommand") if (validCommand && distinctCrossConfigs.size > 1) {
case (version, projects) => state.log.warn(
// First switch scala version, then use the all command to run the command on each project concurrently "Issuing a cross building command, but not all sub projects have the same cross build " +
Seq(s"$SwitchCommand $verbose $version", "configuration. This could result in subprojects cross building against Scala versions that they are " +
projects.map(_ + "/" + aggCommand).mkString("all ", " ", "")) "not compatible with. Try issuing cross building command with tasks instead, since sbt will be able " +
"to ensure that cross building is only done using configured project and Scala version combinations " +
"that are configured.")
state.log.debug("Scala versions configuration is:")
projCrossVersions.foreach {
case (project, versions) => state.log.debug(s"$project: $versions")
}
}
// Execute using a blanket switch
projCrossVersions.toMap.apply(currentRef).flatMap { version =>
// Force scala version
Seq(s"$SwitchCommand $verbose $version!", aggCommand)
}
case Right(_) =>
// We have a key, we're likely to be able to cross build this using the per project behaviour.
// Group all the projects by scala version
projVersions.groupBy(_._2).mapValues(_.map(_._1)).toSeq.flatMap {
case (version, Seq(project)) =>
// If only one project for a version, issue it directly
Seq(s"$SwitchCommand $verbose $version $project/$aggCommand")
case (version, projects) if aggCommand.contains(" ") =>
// If the command contains a space, then the `all` command won't work because it doesn't support issuing
// commands with spaces, so revert to running the command on each project one at a time
s"$SwitchCommand $verbose $version" :: projects.map(project =>
s"$project/$aggCommand")
case (version, projects) =>
// First switch scala version, then use the all command to run the command on each project concurrently
Seq(s"$SwitchCommand $verbose $version",
projects.map(_ + "/" + aggCommand).mkString("all ", " ", ""))
}
} }
allCommands.toList ::: CrossRestoreSessionCommand :: captureCurrentSession(state, x) allCommands.toList ::: CrossRestoreSessionCommand :: captureCurrentSession(state, x)

View File

@ -316,7 +316,9 @@ object Defaults extends BuildCommon {
includeFilter in unmanagedSources, includeFilter in unmanagedSources,
excludeFilter in unmanagedSources).value, excludeFilter in unmanagedSources).value,
watchSources in ConfigGlobal ++= { watchSources in ConfigGlobal ++= {
val bases = unmanagedSourceDirectories.value val baseDir = baseDirectory.value
val bases = unmanagedSourceDirectories.value ++ (if (sourcesInBase.value) Seq(baseDir)
else Seq.empty)
val include = (includeFilter in unmanagedSources).value val include = (includeFilter in unmanagedSources).value
val exclude = (excludeFilter in unmanagedSources).value val exclude = (excludeFilter in unmanagedSources).value
bases.map(b => new Source(b, include, exclude)) bases.map(b => new Source(b, include, exclude))
@ -388,14 +390,7 @@ object Defaults extends BuildCommon {
val _ = clean.value val _ = clean.value
IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log) IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log)
}, },
scalaCompilerBridgeSource := { scalaCompilerBridgeSource := ZincUtil.getDefaultBridgeModule(scalaVersion.value)
if (ScalaInstance.isDotty(scalaVersion.value))
// Maintained at https://github.com/lampepfl/dotty/tree/master/sbt-bridge
ModuleID(scalaOrganization.value, "dotty-sbt-bridge", scalaVersion.value)
.withConfigurations(Some("component"))
.sources()
else ZincUtil.getDefaultBridgeModule(scalaVersion.value)
}
) )
// must be a val: duplication detected by object identity // must be a val: duplication detected by object identity
private[this] lazy val compileBaseGlobal: Seq[Setting[_]] = globalDefaults( private[this] lazy val compileBaseGlobal: Seq[Setting[_]] = globalDefaults(
@ -501,8 +496,8 @@ object Defaults extends BuildCommon {
selectMainClass := mainClass.value orElse askForMainClass(discoveredMainClasses.value), selectMainClass := mainClass.value orElse askForMainClass(discoveredMainClasses.value),
mainClass in run := (selectMainClass in run).value, mainClass in run := (selectMainClass in run).value,
mainClass := pickMainClassOrWarn(discoveredMainClasses.value, streams.value.log), mainClass := pickMainClassOrWarn(discoveredMainClasses.value, streams.value.log),
runMain := runMainTask(fullClasspath, runner in run).evaluated, runMain := foregroundRunMainTask.evaluated,
run := runTask(fullClasspath, mainClass in run, runner in run).evaluated, run := foregroundRunTask.evaluated,
copyResources := copyResourcesTask.value, copyResources := copyResourcesTask.value,
// note that we use the same runner and mainClass as plain run // note that we use the same runner and mainClass as plain run
bgRunMain := bgRunMainTask(exportedProductJars, bgRunMain := bgRunMainTask(exportedProductJars,
@ -1166,14 +1161,14 @@ object Defaults extends BuildCommon {
Def.inputTask { Def.inputTask {
val handle = bgRunMain.evaluated val handle = bgRunMain.evaluated
val service = bgJobService.value val service = bgJobService.value
service.waitFor(handle) service.waitForTry(handle).get
} }
// run calls bgRun in the background and waits for the result. // run calls bgRun in the background and waits for the result.
def foregroundRunTask: Initialize[InputTask[Unit]] = def foregroundRunTask: Initialize[InputTask[Unit]] =
Def.inputTask { Def.inputTask {
val handle = bgRun.evaluated val handle = bgRun.evaluated
val service = bgJobService.value val service = bgJobService.value
service.waitFor(handle) service.waitForTry(handle).get
} }
def runMainTask(classpath: Initialize[Task[Classpath]], def runMainTask(classpath: Initialize[Task[Classpath]],
scalaRun: Initialize[Task[ScalaRun]]): Initialize[InputTask[Unit]] = { scalaRun: Initialize[Task[ScalaRun]]): Initialize[InputTask[Unit]] = {
@ -1538,8 +1533,11 @@ object Defaults extends BuildCommon {
lazy val configSettings lazy val configSettings
: Seq[Setting[_]] = Classpaths.configSettings ++ configTasks ++ configPaths ++ packageConfig ++ Classpaths.compilerPluginConfig ++ deprecationSettings : Seq[Setting[_]] = Classpaths.configSettings ++ configTasks ++ configPaths ++ packageConfig ++ Classpaths.compilerPluginConfig ++ deprecationSettings
lazy val compileSettings lazy val compileSettings: Seq[Setting[_]] =
: Seq[Setting[_]] = configSettings ++ (mainBgRunMainTask +: mainBgRunTask +: addBaseSources) ++ Classpaths.addUnmanagedLibrary configSettings ++
(mainBgRunMainTask +: mainBgRunTask +: addBaseSources) ++
Classpaths.addUnmanagedLibrary
lazy val testSettings: Seq[Setting[_]] = configSettings ++ testTasks lazy val testSettings: Seq[Setting[_]] = configSettings ++ testTasks
lazy val itSettings: Seq[Setting[_]] = inConfig(IntegrationTest)(testSettings) lazy val itSettings: Seq[Setting[_]] = inConfig(IntegrationTest)(testSettings)
@ -2961,7 +2959,7 @@ trait BuildExtra extends BuildCommon with DefExtra {
*/ */
def addSbtPlugin(dependency: ModuleID): Setting[Seq[ModuleID]] = def addSbtPlugin(dependency: ModuleID): Setting[Seq[ModuleID]] =
libraryDependencies += { libraryDependencies += {
val sbtV = (sbtBinaryVersion in update).value val sbtV = (sbtBinaryVersion in pluginCrossBuild).value
val scalaV = (scalaBinaryVersion in update).value val scalaV = (scalaBinaryVersion in update).value
sbtPluginExtra(dependency, sbtV, scalaV) sbtPluginExtra(dependency, sbtV, scalaV)
} }

View File

@ -37,7 +37,7 @@ import sbt.internal.{
LogManager LogManager
} }
import sbt.io.{ FileFilter, WatchService } import sbt.io.{ FileFilter, WatchService }
import sbt.internal.io.{ Source, WatchState } import sbt.internal.io.WatchState
import sbt.internal.util.{ AttributeKey, SourcePosition } import sbt.internal.util.{ AttributeKey, SourcePosition }
import sbt.librarymanagement.Configurations.CompilerPlugin import sbt.librarymanagement.Configurations.CompilerPlugin
@ -132,8 +132,8 @@ object Keys {
val suppressSbtShellNotification = settingKey[Boolean]("""True to suppress the "Executing in batch mode.." message.""").withRank(CSetting) val suppressSbtShellNotification = settingKey[Boolean]("""True to suppress the "Executing in batch mode.." message.""").withRank(CSetting)
val pollInterval = settingKey[FiniteDuration]("Interval between checks for modified sources by the continuous execution command.").withRank(BMinusSetting) val pollInterval = settingKey[FiniteDuration]("Interval between checks for modified sources by the continuous execution command.").withRank(BMinusSetting)
val watchService = settingKey[() => WatchService]("Service to use to monitor file system changes.").withRank(BMinusSetting) val watchService = settingKey[() => WatchService]("Service to use to monitor file system changes.").withRank(BMinusSetting)
val watchSources = taskKey[Seq[Source]]("Defines the sources in this project for continuous execution to watch for changes.").withRank(BMinusSetting) val watchSources = taskKey[Seq[Watched.WatchSource]]("Defines the sources in this project for continuous execution to watch for changes.").withRank(BMinusSetting)
val watchTransitiveSources = taskKey[Seq[Source]]("Defines the sources in all projects for continuous execution to watch.").withRank(CSetting) val watchTransitiveSources = taskKey[Seq[Watched.WatchSource]]("Defines the sources in all projects for continuous execution to watch.").withRank(CSetting)
val watchingMessage = settingKey[WatchState => String]("The message to show when triggered execution waits for sources to change.").withRank(DSetting) val watchingMessage = settingKey[WatchState => String]("The message to show when triggered execution waits for sources to change.").withRank(DSetting)
val triggeredMessage = settingKey[WatchState => String]("The message to show before triggered execution executes an action after sources change.").withRank(DSetting) val triggeredMessage = settingKey[WatchState => String]("The message to show before triggered execution executes an action after sources change.").withRank(DSetting)

View File

@ -5,6 +5,7 @@ import java.util.concurrent.atomic.AtomicLong
import java.io.Closeable import java.io.Closeable
import Def.{ ScopedKey, Setting, Classpath } import Def.{ ScopedKey, Setting, Classpath }
import scala.concurrent.ExecutionContext import scala.concurrent.ExecutionContext
import scala.util.Try
import Scope.GlobalScope import Scope.GlobalScope
import java.io.File import java.io.File
import sbt.io.{ IO, Hash } import sbt.io.{ IO, Hash }
@ -18,6 +19,13 @@ import sbt.internal.util.{ Attributed, ManagedLogger }
private[sbt] abstract class BackgroundJob { private[sbt] abstract class BackgroundJob {
def humanReadableName: String def humanReadableName: String
def awaitTermination(): Unit def awaitTermination(): Unit
/** This waits till the job ends, and returns inner error via `Try`. */
def awaitTerminationTry(): Try[Unit] = {
// This implementation is provided only for backward compatibility.
Try(awaitTermination())
}
def shutdown(): Unit def shutdown(): Unit
// this should be true on construction and stay true until // this should be true on construction and stay true until
// the job is complete // the job is complete
@ -132,15 +140,27 @@ private[sbt] abstract class AbstractBackgroundJobService extends BackgroundJobSe
private def withHandle(job: JobHandle)(f: ThreadJobHandle => Unit): Unit = job match { private def withHandle(job: JobHandle)(f: ThreadJobHandle => Unit): Unit = job match {
case handle: ThreadJobHandle @unchecked => f(handle) case handle: ThreadJobHandle @unchecked => f(handle)
case dead: DeadHandle @unchecked => () // nothing to stop or wait for case _: DeadHandle @unchecked => () // nothing to stop or wait for
case other => case other =>
sys.error( sys.error(
s"BackgroundJobHandle does not originate with the current BackgroundJobService: $other") s"BackgroundJobHandle does not originate with the current BackgroundJobService: $other")
} }
private def withHandleTry(job: JobHandle)(f: ThreadJobHandle => Try[Unit]): Try[Unit] =
job match {
case handle: ThreadJobHandle @unchecked => f(handle)
case _: DeadHandle @unchecked => Try(()) // nothing to stop or wait for
case other =>
Try(sys.error(
s"BackgroundJobHandle does not originate with the current BackgroundJobService: $other"))
}
override def stop(job: JobHandle): Unit = override def stop(job: JobHandle): Unit =
withHandle(job)(_.job.shutdown()) withHandle(job)(_.job.shutdown())
override def waitForTry(job: JobHandle): Try[Unit] =
withHandleTry(job)(_.job.awaitTerminationTry())
override def waitFor(job: JobHandle): Unit = override def waitFor(job: JobHandle): Unit =
withHandle(job)(_.job.awaitTermination()) withHandle(job)(_.job.awaitTermination())
@ -212,6 +232,9 @@ private[sbt] class BackgroundThreadPool extends java.io.Closeable {
@volatile @volatile
private var status: Status = Waiting private var status: Status = Waiting
// This is used to capture exceptions that are caught in this background job.
private var exitTry: Option[Try[Unit]] = None
// double-finally for extra paranoia that we will finishedLatch.countDown // double-finally for extra paranoia that we will finishedLatch.countDown
override def run() = override def run() =
try { try {
@ -226,7 +249,11 @@ private[sbt] class BackgroundThreadPool extends java.io.Closeable {
throw new RuntimeException("Impossible status of bg thread") throw new RuntimeException("Impossible status of bg thread")
} }
} }
try { if (go) body() } finally cleanup() try {
if (go) {
exitTry = Option(Try(body()))
}
} finally cleanup()
} finally finishedLatch.countDown() } finally finishedLatch.countDown()
private class StopListener(val callback: () => Unit, val executionContext: ExecutionContext) private class StopListener(val callback: () => Unit, val executionContext: ExecutionContext)
@ -269,6 +296,12 @@ private[sbt] class BackgroundThreadPool extends java.io.Closeable {
result result
} }
override def awaitTermination(): Unit = finishedLatch.await() override def awaitTermination(): Unit = finishedLatch.await()
override def awaitTerminationTry(): Try[Unit] = {
awaitTermination()
exitTry.getOrElse(Try(()))
}
override def humanReadableName: String = taskName override def humanReadableName: String = taskName
override def isRunning(): Boolean = override def isRunning(): Boolean =
status match { status match {

View File

@ -0,0 +1,7 @@
### Bug fixes
- Fixes `addSbtPlugin` to use the correct version of sbt. [#3393][]/[#3397][] by [@dwijnand][]
[#3393]: https://github.com/sbt/sbt/issues/3393
[#3397]: https://github.com/sbt/sbt/pull/3397
[@dwijnand]: http://github.com/dwijnand

49
notes/1.0.1.markdown Normal file
View File

@ -0,0 +1,49 @@
This is a hotfix release for sbt 1.0.x series.
### Improvements
- Various improves around watch source feature. See below.
### Bug fixes
- Fixes command support for cross building `+` command. The `+` added to sbt 1.0 traveres over the subprojects, respecting `crossScalaVersions`; however, it no longer accepted commands as arguments. This brings back the support for it. [#3446][3446] by [@jroper][@jroper]
- Fixes `addSbtPlugin` to use the correct version of sbt during cross building. [#3442][3442] by [@dwijnand][@dwijnand]
- Fixes `run in Compile` task not including `Runtime` configuration, by reimplementing `run` in terms of `bgRun`. [#3477][3477] by [@eed3si9n][@eed3si9n]
- Shows `actual` as a potential option of `inspect` [#3335][3335] by [@Duhemm][@Duhemm]
- Includes base directory to watched sources. [#3439][3439] by [@Duhemm][@Duhemm]
- Adds an attempt to workaround intermittent `NullPointerException` arround logging. [util#121][util121] by [@eed3si9n][@eed3si9n]
- Reverts a bad forward porting. [#3481][3481] by [@eed3si9n][@eed3si9n]
### WatchSource
The watch source feature went through a major change from sbt 0.13 to sbt 1.0 using NIO; however, it did not have clear migration path, so we are rectifying that in sbt 1.0.1.
First, `sbt.WatchSource` is a new alias for `sbt.internal.io.Source`. Hopefully this is easy enough to remember because the key is named `watchSources`. Next, `def apply(base: File)` and `def apply(base: File, includeFilter: FileFilter, excludeFilter: FileFilter)` constructors were added to the companion object of `sbt.WatchSource`.
For backward compatiblity, sbt 1.0.1 adds `+=` support (`Append` instance) from `File` to `Seq[WatchSource]`.
So, if you have a directory you want to watch:
watchSources += WatchSource(sourceDirectory.value)
If you have a list of files:
watchSources ++= (sourceDirectory.value ** "*.scala").get
[#3438][3438] by [@Duhemm][@Duhemm]; [#3478][3478] and [io#74][io74] by [@eed3si9n][@eed3si9n]
[3335]: https://github.com/sbt/sbt/pull/3335
[3438]: https://github.com/sbt/sbt/pull/3438
[3478]: https://github.com/sbt/sbt/pull/3478
[3439]: https://github.com/sbt/sbt/pull/3439
[io74]: https://github.com/sbt/io/pull/74
[3442]: https://github.com/sbt/sbt/pull/3442
[3446]: https://github.com/sbt/sbt/pull/3446
[3477]: https://github.com/sbt/sbt/pull/3477
[3481]: https://github.com/sbt/sbt/pull/3481
[util121]: https://github.com/sbt/util/pull/121
[@eed3si9n]: https://github.com/eed3si9n
[@dwijnand]: http://github.com/dwijnand
[@jvican]: https://github.com/jvican
[@Duhemm]: https://github.com/Duhemm
[@jroper]: https://github.com/jroper

View File

@ -12,8 +12,8 @@ object Dependencies {
val baseScalaVersion = scala212 val baseScalaVersion = scala212
// sbt modules // sbt modules
private val ioVersion = "1.0.0" private val ioVersion = "1.0.1"
private val utilVersion = "1.0.0" private val utilVersion = "1.0.1"
private val lmVersion = "1.0.0" private val lmVersion = "1.0.0"
private val zincVersion = "1.0.0" private val zincVersion = "1.0.0"

View File

@ -1 +1 @@
sbt.version=1.0.0-RC3 sbt.version=1.0.0

View File

@ -50,6 +50,8 @@ trait Import {
type RichFile = sbt.io.RichFile type RichFile = sbt.io.RichFile
type SimpleFileFilter = sbt.io.SimpleFileFilter type SimpleFileFilter = sbt.io.SimpleFileFilter
type SimpleFilter = sbt.io.SimpleFilter type SimpleFilter = sbt.io.SimpleFilter
type WatchSource = sbt.internal.io.Source
val WatchSource = sbt.internal.io.Source
// sbt.util // sbt.util
type AbstractLogger = sbt.util.AbstractLogger type AbstractLogger = sbt.util.AbstractLogger

View File

@ -19,3 +19,5 @@ lazy val fooPlugin =(project in file("sbt-foo")).
scalaVersion := "2.12.1", scalaVersion := "2.12.1",
crossScalaVersions := Seq("2.12.1") crossScalaVersions := Seq("2.12.1")
) )
addCommandAlias("build", "compile")

View File

@ -36,3 +36,13 @@ $ exists lib/target/scala-2.11
# -$ exists lib/target/scala-2.12 # -$ exists lib/target/scala-2.12
# -$ exists sbt-foo/target/scala-2.12 # -$ exists sbt-foo/target/scala-2.12
# $ exists sbt-foo/target/scala-2.11 # $ exists sbt-foo/target/scala-2.11
> clean
# Test legacy cross build with command support
> + build
# Uses the root project scala version config, which is only configured to build for Scala 2.12
$ exists lib/target/scala-2.12
-$ exists lib/target/scala-2.11
$ exists sbt-foo/target/scala-2.12
-$ exists sbt-foo/target/scala-2.11

View File

@ -1,6 +1,9 @@
scalaVersion in ThisBuild := "2.12.3"
libraryDependencies ++= Seq( libraryDependencies ++= Seq(
"com.novocode" % "junit-interface" % "0.5" % "test", "com.novocode" % "junit-interface" % "0.5" % Test,
"junit" % "junit" % "4.8" % "test" "junit" % "junit" % "4.8" % Test,
"commons-io" % "commons-io" % "2.5" % Runtime,
) )
libraryDependencies += scalaVersion("org.scala-lang" % "scala-compiler" % _ ).value libraryDependencies += scalaVersion("org.scala-lang" % "scala-compiler" % _ ).value

View File

@ -28,10 +28,11 @@ class Foo {
catch { case _: URISyntaxException => new File(url.getPath) } catch { case _: URISyntaxException => new File(url.getPath) }
} }
object Test object Test {
{ def main(args: Array[String]): Unit = {
def main(args: Array[String]) // test that Runtime configuration is included
{ Class.forName("org.apache.commons.io.ByteOrderMark")
val foo = new Foo val foo = new Foo
args.foreach { arg => foo.eval(arg) == arg.toInt } args.foreach { arg => foo.eval(arg) == arg.toInt }
} }

View File

@ -4,39 +4,38 @@ val buildCrossList = List("2.10.6", "2.11.11", "2.12.2")
scalaVersion in ThisBuild := "2.12.2" scalaVersion in ThisBuild := "2.12.2"
crossScalaVersions in ThisBuild := buildCrossList crossScalaVersions in ThisBuild := buildCrossList
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0")
lazy val root = (project in file(".")) lazy val root = (project in file("."))
.settings( .settings(
sbtPlugin := true, sbtPlugin := true,
TaskKey[Unit]("check") := { TaskKey[Unit]("check") := mkCheck("2.12", "1.0").value,
val crossV = (sbtVersion in pluginCrossBuild).value TaskKey[Unit]("check2") := mkCheck("2.10", "0.13").value
val sv = projectID.value.extraAttributes("e:scalaVersion")
assert(sbtVersion.value startsWith baseSbt, s"Wrong sbt version: ${sbtVersion.value}")
assert(sv == "2.12", s"Wrong e:scalaVersion: $sv")
assert(scalaBinaryVersion.value == "2.12", s"Wrong Scala binary version: ${scalaBinaryVersion.value}")
assert(crossV startsWith "1.0.", s"Wrong `sbtVersion in pluginCrossBuild`: $crossV")
// crossScalaVersions in app should not be affected
val appCrossScalaVersions = (crossScalaVersions in app).value.toList
val appScalaVersion = (scalaVersion in app).value
assert(appCrossScalaVersions == buildCrossList, s"Wrong `crossScalaVersions in app`: $appCrossScalaVersions")
assert(appScalaVersion startsWith "2.12", s"Wrong `scalaVersion in app`: $appScalaVersion")
},
TaskKey[Unit]("check2") := {
val crossV = (sbtVersion in pluginCrossBuild).value
val sv = projectID.value.extraAttributes("e:scalaVersion")
assert(sbtVersion.value startsWith baseSbt, s"Wrong sbt version: ${sbtVersion.value}")
assert(sv == "2.10", s"Wrong e:scalaVersion: $sv")
assert(scalaBinaryVersion.value == "2.10", s"Wrong Scala binary version: ${scalaBinaryVersion.value}")
assert(crossV startsWith "0.13", s"Wrong `sbtVersion in pluginCrossBuild`: $crossV")
// ^^ should not affect app's crossScalaVersions
val appCrossScalaVersions = (crossScalaVersions in app).value.toList
val appScalaVersion = (scalaVersion in app).value
assert(appCrossScalaVersions == buildCrossList, s"Wrong `crossScalaVersions in app`: $appCrossScalaVersions")
assert(appScalaVersion startsWith "2.12", s"Wrong `scalaVersion in app`: $appScalaVersion")
}
) )
lazy val app = (project in file("app")) lazy val app = (project in file("app"))
def mkCheck(scalaBinV: String, sbtBinVer: String) = Def task {
val crossV = (sbtVersion in pluginCrossBuild).value
val crossBinV = (sbtBinaryVersion in pluginCrossBuild).value
val sv = projectID.value.extraAttributes("e:scalaVersion")
assert(sbtVersion.value startsWith baseSbt, s"Wrong sbt version: ${sbtVersion.value}")
assert(sv == scalaBinV, s"Wrong e:scalaVersion: $sv")
assert(scalaBinaryVersion.value == scalaBinV, s"Wrong Scala binary version: ${scalaBinaryVersion.value}")
assert(crossV startsWith sbtBinVer, s"Wrong `sbtVersion in pluginCrossBuild`: $crossV")
val ur = update.value
val cr = ur.configuration(Compile).get
val mr = cr.modules.find(mr => mr.module.organization == "com.eed3si9n" && mr.module.name == "sbt-buildinfo").get
val plugSv = mr.module.extraAttributes("scalaVersion")
val plugSbtV = mr.module.extraAttributes("sbtVersion")
assert(plugSv == scalaBinV, s"Wrong plugin scalaVersion: $plugSv")
assert(plugSbtV == sbtBinVer, s"Wrong plugin scalaVersion: $sbtBinVer")
// crossScalaVersions in app should not be affected, per se or after ^^
val appCrossScalaVersions = (crossScalaVersions in app).value.toList
val appScalaVersion = (scalaVersion in app).value
assert(appCrossScalaVersions == buildCrossList, s"Wrong `crossScalaVersions in app`: $appCrossScalaVersions")
assert(appScalaVersion startsWith "2.12", s"Wrong `scalaVersion in app`: $appScalaVersion")
}

View File

@ -17,7 +17,10 @@ def unpackageSettings(name: String) = Seq(
unmanagedSourceDirectories := (baseDirectory.value / name) :: Nil, unmanagedSourceDirectories := (baseDirectory.value / name) :: Nil,
excludeFilter in unmanagedResources := (includeFilter in unmanagedSources).value, excludeFilter in unmanagedResources := (includeFilter in unmanagedSources).value,
unmanagedResourceDirectories := unmanagedSourceDirectories.value, unmanagedResourceDirectories := unmanagedSourceDirectories.value,
unpackage := IO.unzip(artifactPath in packageSrc value, baseDirectory.value / name) unpackage := {
IO.unzip(artifactPath in packageSrc value, baseDirectory.value / name)
IO.delete(baseDirectory.value / name / "META-INF")
}
) )
val unpackage = TaskKey[Unit]("unpackage") val unpackage = TaskKey[Unit]("unpackage")