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 project/*1of2"
- 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="repoOverrideTest:scripted dependency-management/*"

View File

@ -1,6 +1,7 @@
import Util._
import Dependencies._
import Sxr.sxr
import com.typesafe.tools.mima.core._, ProblemFilters._
// ThisBuild settings take lower precedence,
// but can be shared across the multi projects.
@ -66,7 +67,7 @@ def testedBaseSettings: Seq[Setting[_]] =
val mimaSettings = Def settings (
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)
)
)
@ -382,9 +383,18 @@ lazy val sbtProj = (project in file("sbt"))
crossScalaVersions := Seq(baseScalaVersion),
crossPaths := false,
mimaSettings,
mimaBinaryIssueFilters ++= sbtIgnoredProblems,
)
.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 {
val result = scriptedSource(dir => (s: State) => Scripted.scriptedParser(dir)).parsed
// publishLocalBinAll.value // TODO: Restore scripted needing only binary jars.

View File

@ -6,11 +6,12 @@ package sbt
import BasicCommandStrings.ClearOnFailure
import State.FailureWall
import annotation.tailrec
import java.io.File
import java.nio.file.FileSystems
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.util.AttributeKey
import sbt.internal.util.Types.const
@ -18,7 +19,7 @@ import sbt.internal.util.Types.const
trait Watched {
/** 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)
/**
@ -44,6 +45,30 @@ object Watched {
val clearWhenTriggered: WatchState => String = const(clearScreen)
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
def multi(base: Watched, paths: Seq[Watched]): Watched =

View File

@ -6,6 +6,8 @@ import scala.annotation.implicitNotFound
import sbt.internal.util.Attributed
import Def.Initialize
import reflect.internal.annotations.compileTimeOnly
import sbt.internal.io.Source
import sbt.io.{ AllPassFilter, NothingFilter }
object Append {
@implicitNotFound(
@ -96,4 +98,11 @@ object Append {
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 :+ _)
}
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 sbt.internal.util.complete._
import java.io.File
import scala.util.Try
abstract class BackgroundJobService extends Closeable {
@ -24,6 +25,12 @@ abstract class BackgroundJobService extends Closeable {
def shutdown(): Unit
def jobs: Vector[JobHandle]
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
/** Copies classpath to temporary directories. */

View File

@ -3,7 +3,7 @@
*/
package sbt
import Keys._
import Keys.{ version, _ }
import sbt.internal.util.complete.{ DefaultParsers, Parser }
import sbt.internal.util.AttributeKey
import DefaultParsers._
@ -18,6 +18,7 @@ import sbt.internal.CommandStrings.{
}
import java.io.File
import sbt.internal.Act
import sbt.internal.inc.ScalaInstance
import sbt.io.IO
import sbt.librarymanagement.CrossVersion
@ -125,10 +126,13 @@ object Cross {
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
// 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 =>
crossVersions(x, proj) map { (proj.project, _) }
val projVersions = (projCrossVersions flatMap {
case (proj, versions) => versions map { proj.project -> _ }
}).toList
val verbose = if (args.verbose) "-v" else ""
@ -136,19 +140,51 @@ object Cross {
if (projVersions.isEmpty) {
state
} else {
// Group all the projects by scala version
val allCommands = 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 ", " ", ""))
// Detect whether a task or command has been issued
val allCommands = Parser.parse(aggCommand, Act.aggregatedKeyParser(x)) match {
case Left(_) =>
// It's definitely not a task, check if it's a valid command, because we don't want to emit the warning
// message below for typos.
val validCommand = Parser.parse(aggCommand, state.combinedParser).isRight
val distinctCrossConfigs = projCrossVersions.map(_._2.toSet).distinct
if (validCommand && distinctCrossConfigs.size > 1) {
state.log.warn(
"Issuing a cross building command, but not all sub projects have the same cross build " +
"configuration. This could result in subprojects cross building against Scala versions that they are " +
"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)

View File

@ -316,7 +316,9 @@ object Defaults extends BuildCommon {
includeFilter in unmanagedSources,
excludeFilter in unmanagedSources).value,
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 exclude = (excludeFilter in unmanagedSources).value
bases.map(b => new Source(b, include, exclude))
@ -388,14 +390,7 @@ object Defaults extends BuildCommon {
val _ = clean.value
IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log)
},
scalaCompilerBridgeSource := {
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)
}
scalaCompilerBridgeSource := ZincUtil.getDefaultBridgeModule(scalaVersion.value)
)
// must be a val: duplication detected by object identity
private[this] lazy val compileBaseGlobal: Seq[Setting[_]] = globalDefaults(
@ -501,8 +496,8 @@ object Defaults extends BuildCommon {
selectMainClass := mainClass.value orElse askForMainClass(discoveredMainClasses.value),
mainClass in run := (selectMainClass in run).value,
mainClass := pickMainClassOrWarn(discoveredMainClasses.value, streams.value.log),
runMain := runMainTask(fullClasspath, runner in run).evaluated,
run := runTask(fullClasspath, mainClass in run, runner in run).evaluated,
runMain := foregroundRunMainTask.evaluated,
run := foregroundRunTask.evaluated,
copyResources := copyResourcesTask.value,
// note that we use the same runner and mainClass as plain run
bgRunMain := bgRunMainTask(exportedProductJars,
@ -1166,14 +1161,14 @@ object Defaults extends BuildCommon {
Def.inputTask {
val handle = bgRunMain.evaluated
val service = bgJobService.value
service.waitFor(handle)
service.waitForTry(handle).get
}
// run calls bgRun in the background and waits for the result.
def foregroundRunTask: Initialize[InputTask[Unit]] =
Def.inputTask {
val handle = bgRun.evaluated
val service = bgJobService.value
service.waitFor(handle)
service.waitForTry(handle).get
}
def runMainTask(classpath: Initialize[Task[Classpath]],
scalaRun: Initialize[Task[ScalaRun]]): Initialize[InputTask[Unit]] = {
@ -1538,8 +1533,11 @@ object Defaults extends BuildCommon {
lazy val configSettings
: Seq[Setting[_]] = Classpaths.configSettings ++ configTasks ++ configPaths ++ packageConfig ++ Classpaths.compilerPluginConfig ++ deprecationSettings
lazy val compileSettings
: Seq[Setting[_]] = configSettings ++ (mainBgRunMainTask +: mainBgRunTask +: addBaseSources) ++ Classpaths.addUnmanagedLibrary
lazy val compileSettings: Seq[Setting[_]] =
configSettings ++
(mainBgRunMainTask +: mainBgRunTask +: addBaseSources) ++
Classpaths.addUnmanagedLibrary
lazy val testSettings: Seq[Setting[_]] = configSettings ++ testTasks
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]] =
libraryDependencies += {
val sbtV = (sbtBinaryVersion in update).value
val sbtV = (sbtBinaryVersion in pluginCrossBuild).value
val scalaV = (scalaBinaryVersion in update).value
sbtPluginExtra(dependency, sbtV, scalaV)
}

View File

@ -37,7 +37,7 @@ import sbt.internal.{
LogManager
}
import sbt.io.{ FileFilter, WatchService }
import sbt.internal.io.{ Source, WatchState }
import sbt.internal.io.WatchState
import sbt.internal.util.{ AttributeKey, SourcePosition }
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 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 watchSources = taskKey[Seq[Source]]("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 watchSources = taskKey[Seq[Watched.WatchSource]]("Defines the sources in this project for continuous execution to watch for changes.").withRank(BMinusSetting)
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 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 Def.{ ScopedKey, Setting, Classpath }
import scala.concurrent.ExecutionContext
import scala.util.Try
import Scope.GlobalScope
import java.io.File
import sbt.io.{ IO, Hash }
@ -18,6 +19,13 @@ import sbt.internal.util.{ Attributed, ManagedLogger }
private[sbt] abstract class BackgroundJob {
def humanReadableName: String
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
// this should be true on construction and stay true until
// 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 {
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 =>
sys.error(
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 =
withHandle(job)(_.job.shutdown())
override def waitForTry(job: JobHandle): Try[Unit] =
withHandleTry(job)(_.job.awaitTerminationTry())
override def waitFor(job: JobHandle): Unit =
withHandle(job)(_.job.awaitTermination())
@ -212,6 +232,9 @@ private[sbt] class BackgroundThreadPool extends java.io.Closeable {
@volatile
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
override def run() =
try {
@ -226,7 +249,11 @@ private[sbt] class BackgroundThreadPool extends java.io.Closeable {
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()
private class StopListener(val callback: () => Unit, val executionContext: ExecutionContext)
@ -269,6 +296,12 @@ private[sbt] class BackgroundThreadPool extends java.io.Closeable {
result
}
override def awaitTermination(): Unit = finishedLatch.await()
override def awaitTerminationTry(): Try[Unit] = {
awaitTermination()
exitTry.getOrElse(Try(()))
}
override def humanReadableName: String = taskName
override def isRunning(): Boolean =
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
// sbt modules
private val ioVersion = "1.0.0"
private val utilVersion = "1.0.0"
private val ioVersion = "1.0.1"
private val utilVersion = "1.0.1"
private val lmVersion = "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 SimpleFileFilter = sbt.io.SimpleFileFilter
type SimpleFilter = sbt.io.SimpleFilter
type WatchSource = sbt.internal.io.Source
val WatchSource = sbt.internal.io.Source
// sbt.util
type AbstractLogger = sbt.util.AbstractLogger

View File

@ -19,3 +19,5 @@ lazy val fooPlugin =(project in file("sbt-foo")).
scalaVersion := "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 sbt-foo/target/scala-2.12
# $ 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(
"com.novocode" % "junit-interface" % "0.5" % "test",
"junit" % "junit" % "4.8" % "test"
"com.novocode" % "junit-interface" % "0.5" % Test,
"junit" % "junit" % "4.8" % Test,
"commons-io" % "commons-io" % "2.5" % Runtime,
)
libraryDependencies += scalaVersion("org.scala-lang" % "scala-compiler" % _ ).value

View File

@ -28,10 +28,11 @@ class Foo {
catch { case _: URISyntaxException => new File(url.getPath) }
}
object Test
{
def main(args: Array[String])
{
object Test {
def main(args: Array[String]): Unit = {
// test that Runtime configuration is included
Class.forName("org.apache.commons.io.ByteOrderMark")
val foo = new Foo
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"
crossScalaVersions in ThisBuild := buildCrossList
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0")
lazy val root = (project in file("."))
.settings(
sbtPlugin := true,
TaskKey[Unit]("check") := {
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.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")
}
TaskKey[Unit]("check") := mkCheck("2.12", "1.0").value,
TaskKey[Unit]("check2") := mkCheck("2.10", "0.13").value
)
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,
excludeFilter in unmanagedResources := (includeFilter in unmanagedSources).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")