From 2d0aafc8b032a7e720228b852af76c7255c8c04a Mon Sep 17 00:00:00 2001 From: Josh Suereth Date: Fri, 8 Aug 2014 15:29:30 -0400 Subject: [PATCH] Allow root plugins to be disabled. Fixes #1455 * Add a mechanism to detect if a plugin clause includes/excludes a particular plugin. * Add a filter for our "enabling" clauses so that user-excluded root plugins do not show up. * Add a test to ensure this succeed. --- main/src/main/scala/sbt/Plugins.scala | 26 ++++++++++++++++++- .../sbt-test/project/auto-plugins/build.sbt | 4 +++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/main/src/main/scala/sbt/Plugins.scala b/main/src/main/scala/sbt/Plugins.scala index 52bcd288a..6bad8f617 100644 --- a/main/src/main/scala/sbt/Plugins.scala +++ b/main/src/main/scala/sbt/Plugins.scala @@ -156,8 +156,13 @@ object Plugins extends PluginsFunctions // circular dependencies in the logic. val allRequirementsClause = defined.filterNot(_.isRoot).flatMap(d => asRequirementsClauses(d)) val allEnabledByClause = defined.filterNot(_.isRoot).flatMap(d => asEnabledByClauses(d)) + + // Note: Here is where the function begins. We're given a list of plugins now. (requestedPlugins, log) => { - val alwaysEnabled: List[AutoPlugin] = defined.filter(_.isAlwaysEnabled) + def explicitlyDisabled(p: AutoPlugin): Boolean = hasExclude(requestedPlugins, p) + val alwaysEnabled: List[AutoPlugin] = defined.filter(_.isAlwaysEnabled).filterNot(explicitlyDisabled) + System.err.println(s"Always Enabled Plugins = ${alwaysEnabled.mkString(", ")}") + System.err.println(s"Requested = $requestedPlugins") val knowlege0: Set[Atom] = ((flatten(requestedPlugins) ++ alwaysEnabled) collect { case x: AutoPlugin => Atom(x.label) }).toSet @@ -282,6 +287,25 @@ ${listConflicts(conflicting)}""") private[sbt] def asExclusions(ap: AutoPlugin): List[AutoPlugin] = flatten(ap.requires).toList collect { case Exclude(x) => x } + // TODO - This doesn't handle nested AND boolean logic... + private[sbt] def hasExclude(n: Plugins, p: AutoPlugin): Boolean = n match { + case `p` => false + case Exclude(`p`) => true + // TODO - This is stupidly advanced. We do a nested check through possible and-ed + // lists of plugins exclusions to see if the plugin ever winds up in an excluded=true case. + // This would handle things like !!p or !(p && z) + case Exclude(n) => hasInclude(n, p) + case And(ns) => ns.forall(n => hasExclude(n, p)) + case b: Basic => false + case Empty => false + } + private[sbt] def hasInclude(n: Plugins, p: AutoPlugin): Boolean = n match { + case `p` => true + case Exclude(n) => hasExclude(n, p) + case And(ns) => ns.forall(n => hasInclude(n, p)) + case b: Basic => false + case Empty => false + } private[this] def flattenConvert(n: Plugins): Seq[Literal] = n match { case And(ns) => convertAll(ns) case b: Basic => convertBasic(b) :: Nil diff --git a/sbt/src/sbt-test/project/auto-plugins/build.sbt b/sbt/src/sbt-test/project/auto-plugins/build.sbt index 5fd1c156a..d8dc8d0db 100644 --- a/sbt/src/sbt-test/project/auto-plugins/build.sbt +++ b/sbt/src/sbt-test/project/auto-plugins/build.sbt @@ -25,6 +25,10 @@ lazy val projH = project.enablePlugins(TopB) lazy val projI = project.enablePlugins(TopC) +// Tests that we can disable an auto-enabled root plugin +lazy val disableAutoNoRequirePlugin = project.disablePlugins(OrgPlugin) + + disablePlugins(plugins.IvyPlugin) check := {