mirror of https://github.com/sbt/sbt.git
[2.x] fix: Fixes plugin toggle precedence between disablePlugins and enablePlugins (#8794)
Treat explicit plugin toggles as last-call-wins for the same plugin. This avoids contradictory include/exclude states when disablePlugins(X) is followed by enablePlugins(X) (and vice versa), aligning behavior with normal override expectations. Apply the same semantics to ProjectMatrix and add regression coverage: - unit tests in main/src/test/scala/ProjectSpec.scala - scripted test in sbt-app/src/sbt-test/project/i1926-disable-enable-plugin
This commit is contained in:
parent
62d7b9a29f
commit
cb498de41d
|
|
@ -343,6 +343,16 @@ ${listConflicts(conflicting)}""")
|
|||
case And(ns) => ns.foldLeft(a)(_ && _)
|
||||
case b: Basic => a && b
|
||||
}
|
||||
|
||||
private[sbt] def overrideWith(current: Plugins, update: Plugins): Plugins = {
|
||||
val opposite: Set[Basic] = flatten(update).map {
|
||||
case Exclude(p) => p: Basic
|
||||
case p: AutoPlugin =>
|
||||
Exclude(p): Basic
|
||||
}.toSet
|
||||
and(remove(current, opposite), update)
|
||||
}
|
||||
|
||||
private[sbt] def remove(a: Plugins, del: Set[Basic]): Plugins = a match {
|
||||
case b: Basic => if (del(b)) Empty else b
|
||||
case Empty => Empty
|
||||
|
|
|
|||
|
|
@ -158,11 +158,18 @@ sealed trait Project extends ProjectDefinition[ProjectReference] with CompositeP
|
|||
* A [[AutoPlugin]] is a common label that is used by plugins to determine what settings, if any, to enable on a project.
|
||||
*/
|
||||
def enablePlugins(ns: Plugins*): Project =
|
||||
setPlugins(ns.foldLeft(plugins)(Plugins.and))
|
||||
setPlugins(ns.foldLeft(plugins)(Plugins.overrideWith))
|
||||
|
||||
/** Disable the given plugins on this project. */
|
||||
def disablePlugins(ps: AutoPlugin*): Project =
|
||||
setPlugins(Plugins.and(plugins, Plugins.And(ps.map(p => Plugins.Exclude(p)).toList)))
|
||||
if ps.isEmpty then this
|
||||
else
|
||||
setPlugins(
|
||||
Plugins.overrideWith(
|
||||
plugins,
|
||||
Plugins.And(ps.map(p => Plugins.Exclude(p)).toList)
|
||||
)
|
||||
)
|
||||
|
||||
private[sbt] def setPlugins(ns: Plugins): Project = copy(plugins = ns)
|
||||
|
||||
|
|
|
|||
|
|
@ -455,10 +455,17 @@ object ProjectMatrix {
|
|||
copy(settings = (settings: Seq[Def.Setting[?]]) ++ Def.settings(ss*))
|
||||
|
||||
override def enablePlugins(ns: Plugins*): ProjectMatrix =
|
||||
setPlugins(ns.foldLeft(plugins)(Plugins.and))
|
||||
setPlugins(ns.foldLeft(plugins)(Plugins.overrideWith))
|
||||
|
||||
override def disablePlugins(ps: AutoPlugin*): ProjectMatrix =
|
||||
setPlugins(Plugins.and(plugins, Plugins.And(ps.map(p => Plugins.Exclude(p)).toList)))
|
||||
if ps.isEmpty then this
|
||||
else
|
||||
setPlugins(
|
||||
Plugins.overrideWith(
|
||||
plugins,
|
||||
Plugins.And(ps.map(p => Plugins.Exclude(p)).toList)
|
||||
)
|
||||
)
|
||||
|
||||
override def configure(ts: (Project => Project)*): ProjectMatrix =
|
||||
copy(transforms = transforms ++ ts)
|
||||
|
|
|
|||
|
|
@ -8,10 +8,30 @@
|
|||
|
||||
package sbt
|
||||
|
||||
import java.io.File
|
||||
|
||||
object ProjectSpec extends verify.BasicTestSuite {
|
||||
object TestPlugin extends AutoPlugin {
|
||||
override def requires: Plugins = empty
|
||||
}
|
||||
|
||||
private val base = new File(".")
|
||||
|
||||
test("Project should normalize projectIDs if they are empty") {
|
||||
assert(Project.normalizeProjectID(emptyFilename) == Right("root"))
|
||||
}
|
||||
|
||||
test("disablePlugins then enablePlugins should keep plugin enabled") {
|
||||
val p = Project("test", base).disablePlugins(TestPlugin).enablePlugins(TestPlugin)
|
||||
assert(Plugins.hasInclude(p.plugins, TestPlugin))
|
||||
assert(!Plugins.hasExclude(p.plugins, TestPlugin))
|
||||
}
|
||||
|
||||
test("enablePlugins then disablePlugins should keep plugin disabled") {
|
||||
val p = Project("test", base).enablePlugins(TestPlugin).disablePlugins(TestPlugin)
|
||||
assert(!Plugins.hasInclude(p.plugins, TestPlugin))
|
||||
assert(Plugins.hasExclude(p.plugins, TestPlugin))
|
||||
}
|
||||
|
||||
def emptyFilename = ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
def myProject(id: String): Project =
|
||||
Project(id, file(id)).disablePlugins(Issue1926Plugin)
|
||||
|
||||
lazy val b = myProject("b").enablePlugins(Issue1926Plugin)
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
def myProject(id: String): Project =
|
||||
Project(id, file(id)).disablePlugins(Issue1926Plugin)
|
||||
|
||||
lazy val a = myProject("a")
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import sbt._
|
||||
|
||||
object Issue1926Plugin extends AutoPlugin {
|
||||
object autoImport {
|
||||
val issue1926Marker = settingKey[String]("Marker setting for issue #1926 test")
|
||||
}
|
||||
|
||||
import autoImport._
|
||||
|
||||
override def requires: Plugins = plugins.JvmPlugin
|
||||
override def trigger = noTrigger
|
||||
override def projectSettings = Seq(issue1926Marker := "enabled")
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
> projects
|
||||
$ copy-file broken.sbt.disabled broken.sbt
|
||||
> reload
|
||||
> show b/issue1926Marker
|
||||
Loading…
Reference in New Issue