Don't overwrite nio build settings with injected settings

The current injection of the new nio keys will overwrite any definitions
of those keys in a build source. This is undesirable. The fix is to
create a mapping of scoped keys to settings and for each inject setting
key, if there is a previous key, put that definition after the injected
definition so that it can override it.
This commit is contained in:
Ethan Atkins 2019-10-07 19:40:17 -07:00
parent d3921d07ce
commit d698d6dcdd
7 changed files with 50 additions and 8 deletions

View File

@ -27,13 +27,26 @@ import scala.collection.immutable.VectorBuilder
private[sbt] object Settings {
private[sbt] def inject(transformed: Seq[Def.Setting[_]]): Seq[Def.Setting[_]] = {
val fileOutputScopes = transformed.collect {
case s if s.key.key == fileOutputs.key && s.key.scope.task.toOption.isDefined =>
s.key.scope
val definedSettings = new java.util.HashMap[Def.ScopedKey[_], VectorBuilder[Def.Setting[_]]]
val fileOutputScopes = transformed.flatMap { s =>
val list = new VectorBuilder[Def.Setting[_]]
definedSettings.putIfAbsent(s.key, list) match {
case null => list += s
case l => l += s
}
if (s.key.key == fileOutputs.key && s.key.scope.task.toOption.isDefined) Some(s.key.scope)
else None
}.toSet
transformed.flatMap {
case s if s.key.key == fileInputs.key => inputPathSettings(s)
case s => s :: maybeAddOutputsAndFileStamps(s, fileOutputScopes)
transformed.flatMap { s =>
val inject =
if (s.key.key == fileInputs.key) inputPathSettings(s)
else maybeAddOutputsAndFileStamps(s, fileOutputScopes)
s +: inject.flatMap { setting =>
(definedSettings.get(setting.key) match {
case null => Vector(setting)
case set => setting +: set.result()
}): Seq[Def.Setting[_]]
}
}
}
@ -126,7 +139,7 @@ private[sbt] object Settings {
private[sbt] def inputPathSettings(setting: Def.Setting[_]): Seq[Def.Setting[_]] = {
val scopedKey = setting.key
val scope = scopedKey.scope
setting :: (Keys.allInputPathsAndAttributes in scope := {
(Keys.allInputPathsAndAttributes in scope := {
val view = (fileTreeView in scope).value
val inputs = (fileInputs in scope).value
val stamper = (inputFileStamper in scope).value

View File

@ -14,7 +14,7 @@ val compileAndCheckNoClassFileUpdates = taskKey[Unit]("Checks that there are no
compileAndCheckNoClassFileUpdates := {
val current = (classFiles / outputFileStamps).value.toSet
val previous = (classFiles / outputFileStamps).previous.getOrElse(Nil).toSet
assert(current == previous)
assert(current == previous, s"$current did not equal $previous")
}
val checkLastModified = inputKey[Unit]("Check the last modified time for a file")
@ -25,6 +25,7 @@ checkLastModified := {
case (file, (negate, expectedLastModified)) =>
val sourceFile = baseDirectory.value / "src" / "main" / "scala" / file
val lastModified = IO.getModifiedTimeOrZero(sourceFile)
println(s"$lastModified $expectedLastModified")
negate match {
case Some(_) => assert(lastModified != expectedLastModified)
case None => assert(lastModified == expectedLastModified)

View File

View File

View File

@ -0,0 +1,24 @@
import java.nio.file.Path
val foo = taskKey[Path]("foo")
// Check a direct override
foo / outputFileStamps := Nil
foo := baseDirectory.value.toPath / "foo.txt"
TaskKey[Unit]("checkFoo") := assert((foo / outputFileStamps).value == Nil)
val bar = taskKey[Path]("bar")
// Check an append
bar / outputFileStamps ++= (baz / outputFileStamps).value
bar / outputFileStamps ++= (baz / outputFileStamps).value
bar := baseDirectory.value.toPath / "bar.txt"
val baz = taskKey[Path]("baz")
baz := baseDirectory.value.toPath / "baz.txt"
TaskKey[Unit]("checkBar") := {
val stamps = (bar / outputFileStamps).value
assert(stamps.length == 3)
val fileNames = stamps.map(_._1.getFileName.toString).toSet
assert(fileNames == Set("bar.txt", "baz.txt"))
}

View File

@ -0,0 +1 @@
foo

View File

@ -0,0 +1,3 @@
> checkBar
> checkFoo