@@ -18,187 +18,210 @@ import Test.Hspec (
1818 )
1919import Text.RawString.QQ (r )
2020
21+ -- The fixtures below mirror the real layout of @sbt -batch -no-colors plugins@:
22+ -- per-project "Enabled plugins in <project>:" sections list one bare plugin
23+ -- FQCN per indented line, and a trailing "Plugins that are loaded to the build
24+ -- but not enabled in any subprojects:" section lists the rest. There is no
25+ -- "<FQCN>: enabled in <scope>" suffix in real output. The sbt 1.9.8 fixtures
26+ -- (default, addDependencyTreePlugin, disabled-mini) are verbatim captures from
27+ -- fossas/scala3-example-project; the remainder follow the same layout.
2128spec :: Spec
2229spec = do
2330 describe " detectDependencyPlugins" $ do
24- it " should detect MiniDependencyTreePlugin (sbt 1.4+ built-in)" $ do
25- detectDependencyPlugins sbt14BuiltinOnly
31+ -- Regression guard for TKT-15490: this is the verbatim `sbt plugins`
32+ -- output for fossas/scala3-example-project (sbt 1.9.8, no plugins.sbt).
33+ -- The built-in MiniDependencyTreePlugin must be detected so the deep
34+ -- `dependencyTree` path runs. A prior refactor anchored detection on a
35+ -- non-existent "<FQCN>: enabled in" suffix, returned False here, and
36+ -- silently fell back to generated poms (Partial graph).
37+ it " detects the built-in MiniDependencyTreePlugin (sbt 1.9.8, no plugins.sbt)" $ do
38+ detectDependencyPlugins sbt198DefaultBuiltin
2639 `shouldBe` DependencyPluginsDetected {hasMiniDependencyTreePlugin = True , dependencyTreePlugin = Nothing }
2740
28- it " should detect explicit modern DependencyTreePlugin (sbt 1.4+ addDependencyTreePlugin)" $ do
29- detectDependencyPlugins sbtModernExplicitPluginOnly
30- `shouldBe` DependencyPluginsDetected {hasMiniDependencyTreePlugin = False , dependencyTreePlugin = Just ModernDependencyTreePlugin }
41+ -- Real sbt 1.9.8 output with `addDependencyTreePlugin` in project/plugins.sbt
42+ -- (the customer setup from TKT-15490). sbt enables the explicit
43+ -- DependencyTreePlugin alongside the built-in MiniDependencyTreePlugin.
44+ it " detects MiniDependencyTreePlugin and modern DependencyTreePlugin together (addDependencyTreePlugin)" $ do
45+ detectDependencyPlugins sbt198AddDependencyTreePlugin
46+ `shouldBe` DependencyPluginsDetected {hasMiniDependencyTreePlugin = True , dependencyTreePlugin = Just ModernDependencyTreePlugin }
3147
32- it " should detect legacy net.virtualvoid plugin (sbt < 1.4 sbt-dependency-graph)" $ do
48+ -- sbt < 1.4 with the third-party net.virtualvoid sbt-dependency-graph
49+ -- plugin. MiniDependencyTreePlugin does not exist before sbt 1.4, so it is
50+ -- absent; routing must dispatch to the legacy lowercase task.
51+ it " detects the legacy net.virtualvoid plugin (sbt-dependency-graph)" $ do
3352 detectDependencyPlugins sbtLegacyVirtualvoidPlugin
3453 `shouldBe` DependencyPluginsDetected {hasMiniDependencyTreePlugin = False , dependencyTreePlugin = Just LegacyDependencyGraphPlugin }
3554
36- -- TKT-14742: When both plugins present, findProjects should prefer MiniDependencyTreePlugin
37- it " should detect both plugins when MiniDependencyTreePlugin AND modern explicit plugin present" $ do
38- detectDependencyPlugins sbt14WithExplicitPlugin
39- `shouldBe` DependencyPluginsDetected {hasMiniDependencyTreePlugin = True , dependencyTreePlugin = Just ModernDependencyTreePlugin }
55+ -- TKT-15490 routing guard: when the modern DependencyTreePlugin is enabled
56+ -- but MiniDependencyTreePlugin is not, findProjects routes to genTreeJson,
57+ -- which must select the uppercase `dependencyBrowseTreeHTML` task. The
58+ -- classification must be Modern (not Legacy lowercase).
59+ it " classifies a modern DependencyTreePlugin with no MiniDependencyTreePlugin as Modern" $ do
60+ detectDependencyPlugins sbtModernWithoutMini
61+ `shouldBe` DependencyPluginsDetected {hasMiniDependencyTreePlugin = False , dependencyTreePlugin = Just ModernDependencyTreePlugin }
4062
41- -- TKT-15490: sbt 1.11.5 with addDependencyTreePlugin and no auto-loaded
42- -- MiniDependencyTreePlugin must be classified as ModernDependencyTreePlugin
43- -- so the analyzer runs the uppercase `dependencyBrowseTreeHTML` task. The
44- -- pre-fix code returned (False, True) and the routing dispatched to the
45- -- legacy lowercase `dependencyBrowseTreeHtml`, which sbt 1.4+ rejects.
46- it " should classify modern DependencyTreePlugin alone as Modern (TKT-15490 routing guard)" $ do
47- let detected = detectDependencyPlugins sbt111ExplicitPluginOnly
48- hasMiniDependencyTreePlugin detected `shouldBe` False
49- dependencyTreePlugin detected `shouldBe` Just ModernDependencyTreePlugin
50-
51- -- If a project somehow lists both the modern and legacy plugin, prefer
52- -- the modern one — sbt 1.4+ wins, since the legacy plugin will not
53- -- function on a sbt that also surfaces sbt.plugins.DependencyTreePlugin.
54- it " should prefer modern DependencyTreePlugin when both modern and legacy are present" $ do
63+ -- If a build somehow enables both the modern and legacy plugin, prefer the
64+ -- modern one — on sbt 1.4+ the legacy lowercase task is unavailable.
65+ it " prefers modern DependencyTreePlugin when both modern and legacy are enabled" $ do
5566 detectDependencyPlugins sbtBothModernAndLegacy
5667 `shouldBe` DependencyPluginsDetected {hasMiniDependencyTreePlugin = False , dependencyTreePlugin = Just ModernDependencyTreePlugin }
5768
58- it " should detect no plugins when neither is present " $ do
69+ it " detects no dependency-tree plugins when none are enabled " $ do
5970 detectDependencyPlugins sbtNoPlugins
6071 `shouldBe` DependencyPluginsDetected {hasMiniDependencyTreePlugin = False , dependencyTreePlugin = Nothing }
6172
62- -- `sbt plugins` lists user-disabled plugins (`disablePlugins(...)`) with a
63- -- ": disabled in <scope>" suffix. The FQCN still appears on those lines,
64- -- so detection must anchor on ": enabled in" to avoid routing to a task
65- -- the active plugin set doesn't provide.
66- it " should not treat MiniDependencyTreePlugin as present when listed as disabled" $ do
67- detectDependencyPlugins sbtDisabledMiniPlugin
73+ -- `disablePlugins(MiniDependencyTreePlugin)` moves the plugin into the
74+ -- trailing "loaded to the build but not enabled in any subprojects"
75+ -- section. This is a verbatim sbt 1.9.8 capture; detection must not treat
76+ -- it as active. An unanchored substring match (the pre-refactor behavior)
77+ -- would wrongly count it.
78+ it " ignores a MiniDependencyTreePlugin listed as loaded-but-not-enabled" $ do
79+ detectDependencyPlugins sbt198DisabledMini
6880 `shouldBe` DependencyPluginsDetected {hasMiniDependencyTreePlugin = False , dependencyTreePlugin = Nothing }
6981
70- it " should not treat modern DependencyTreePlugin as present when listed as disabled " $ do
71- detectDependencyPlugins sbtDisabledModernPlugin
82+ it " ignores a modern DependencyTreePlugin listed as loaded-but-not-enabled " $ do
83+ detectDependencyPlugins sbtDisabledModern
7284 `shouldBe` DependencyPluginsDetected {hasMiniDependencyTreePlugin = False , dependencyTreePlugin = Nothing }
7385
74- -- sbt 1.4+ with only built-in plugin
75- sbt14BuiltinOnly :: Text
76- sbt14BuiltinOnly =
77- [ r |[info] welcome to sbt 1.9.7 (Eclipse Adoptium Java 11.0.21)
78- [ info] loading global plugins from /Users/test/. sbt/1.0/plugins
79- [info] loading project definition from /Users/test/ project/project
86+ -- Verbatim ` sbt -batch -no-colors plugins` output for fossas/scala3-example-project
87+ -- (sbt 1.9.8, no project/plugins.sbt).
88+ sbt198DefaultBuiltin :: Text
89+ sbt198DefaultBuiltin =
90+ [ r |[ info] welcome to sbt 1.9.8 (Homebrew Java 24.0.1)
91+ [info] loading project definition from /private/tmp/scala3-example- project/project
8092[info] loading settings for project root from build.sbt ...
81- [info] set current project to test-project (in build file:/Users/test/project/)
82- [info] In file:/Users/test/project/
83- [info] sbt.plugins.CorePlugin: enabled in root
84- [info] sbt.plugins.IvyPlugin: enabled in root
85- [info] sbt.plugins.JvmPlugin: enabled in root
86- [info] sbt.plugins.MiniDependencyTreePlugin: enabled in root
87- [info] sbt.plugins.SemanticdbPlugin: enabled in root
93+ [info] set current project to scala3-example-project (in build file:/private/tmp/scala3-example-project/)
94+ In build /private/tmp/scala3-example-project/:
95+ Enabled plugins in root:
96+ sbt.plugins.CorePlugin
97+ sbt.plugins.Giter8TemplatePlugin
98+ sbt.plugins.IvyPlugin
99+ sbt.plugins.JUnitXmlReportPlugin
100+ sbt.plugins.JvmPlugin
101+ sbt.plugins.MiniDependencyTreePlugin
102+ sbt.plugins.SemanticdbPlugin
103+ Plugins that are loaded to the build but not enabled in any subprojects:
104+ sbt.ScriptedPlugin
105+ sbt.plugins.SbtPlugin
88106|]
89107
90- -- sbt 1.4+ with explicit addDependencyTreePlugin and no MiniDependencyTreePlugin
91- -- listed (the case the customer in TKT-15490 hit on sbt 1.11.5).
92- sbtModernExplicitPluginOnly :: Text
93- sbtModernExplicitPluginOnly =
94- [r |[info] welcome to sbt 1.3.13 (Eclipse Adoptium Java 11.0.21)
95- [info] loading global plugins from /Users/test/.sbt/1.0/plugins
96- [info] loading project definition from /Users/test/project/project
108+ -- Verbatim sbt 1.9.8 output with `addDependencyTreePlugin` added to
109+ -- project/plugins.sbt (the TKT-15490 customer setup).
110+ sbt198AddDependencyTreePlugin :: Text
111+ sbt198AddDependencyTreePlugin =
112+ [r |[info] welcome to sbt 1.9.8 (Homebrew Java 24.0.1)
113+ [info] loading project definition from /private/tmp/scala3-example-project/project
97114[info] loading settings for project root from build.sbt ...
98- [info] set current project to test-project (in build file:/Users/test/project/)
99- [info] In file:/Users/test/project/
100- [info] sbt.plugins.CorePlugin: enabled in root
101- [info] sbt.plugins.IvyPlugin: enabled in root
102- [info] sbt.plugins.JvmPlugin: enabled in root
103- [info] sbt.plugins.DependencyTreePlugin: enabled in root
115+ [info] set current project to scala3-example-project (in build file:/private/tmp/scala3-example-project/)
116+ In build /private/tmp/scala3-example-project/:
117+ Enabled plugins in root:
118+ sbt.plugins.CorePlugin
119+ sbt.plugins.DependencyTreePlugin
120+ sbt.plugins.Giter8TemplatePlugin
121+ sbt.plugins.IvyPlugin
122+ sbt.plugins.JUnitXmlReportPlugin
123+ sbt.plugins.JvmPlugin
124+ sbt.plugins.MiniDependencyTreePlugin
125+ sbt.plugins.SemanticdbPlugin
126+ Plugins that are loaded to the build but not enabled in any subprojects:
127+ sbt.ScriptedPlugin
128+ sbt.plugins.SbtPlugin
104129|]
105130
106- -- sbt 1.11.5 with addDependencyTreePlugin in plugins.sbt — mirrors the
107- -- customer environment from TKT-15490. The customer reported that the
108- -- pre-fix CLI invoked the lowercase `dependencyBrowseTreeHtml`, which sbt
109- -- 1.4+ rejects.
110- sbt111ExplicitPluginOnly :: Text
111- sbt111ExplicitPluginOnly =
112- [r |[info] welcome to sbt 1.11.5 (Eclipse Adoptium Java 17.0.10)
113- [info] loading global plugins from /Users/test/.sbt/1.0/plugins
114- [info] loading project definition from /Users/test/project/project
115- [info] loading settings for project root from build.sbt ...
116- [info] set current project to test-project (in build file:/Users/test/project/)
117- [info] In file:/Users/test/project/
118- [info] sbt.plugins.CorePlugin: enabled in root
119- [info] sbt.plugins.IvyPlugin: enabled in root
120- [info] sbt.plugins.JvmPlugin: enabled in root
121- [info] sbt.plugins.DependencyTreePlugin: enabled in root
122- |]
123-
124- -- sbt < 1.4 with legacy net.virtualvoid plugin
131+ -- sbt < 1.4 with the legacy net.virtualvoid sbt-dependency-graph plugin.
125132sbtLegacyVirtualvoidPlugin :: Text
126133sbtLegacyVirtualvoidPlugin =
127134 [r |[info] welcome to sbt 1.2.8 (Eclipse Adoptium Java 11.0.21)
128- [info] loading global plugins from /Users/test/.sbt/1.0/plugins
129- [info] loading project definition from /Users/test/project/project
130- [info] loading settings for project root from build.sbt ...
131135[info] set current project to test-project (in build file:/Users/test/project/)
132- [info] In file:/Users/test/project/
133- [info] sbt.plugins.CorePlugin: enabled in root
134- [info] sbt.plugins.IvyPlugin: enabled in root
135- [info] sbt.plugins.JvmPlugin: enabled in root
136- [info] net.virtualvoid.sbt.graph.DependencyGraphPlugin: enabled in root
136+ In build /Users/test/project/:
137+ Enabled plugins in root:
138+ sbt.plugins.CorePlugin
139+ sbt.plugins.IvyPlugin
140+ sbt.plugins.JvmPlugin
141+ net.virtualvoid.sbt.graph.DependencyGraphPlugin
142+ Plugins that are loaded to the build but not enabled in any subprojects:
143+ sbt.plugins.SbtPlugin
137144|]
138145
139- -- TKT-14742: sbt 1.4+ with BOTH built-in and explicit plugin
140- sbt14WithExplicitPlugin :: Text
141- sbt14WithExplicitPlugin =
142- [r |[info] welcome to sbt 1.9.7 (Eclipse Adoptium Java 11.0.21)
143- [info] loading global plugins from /Users/test/.sbt/1.0/plugins
144- [info] loading project definition from /Users/test/project/project
145- [info] loading settings for project root from build.sbt ...
146+ -- Modern DependencyTreePlugin enabled with MiniDependencyTreePlugin disabled
147+ -- (`disablePlugins(MiniDependencyTreePlugin)` alongside addDependencyTreePlugin).
148+ sbtModernWithoutMini :: Text
149+ sbtModernWithoutMini =
150+ [r |[info] welcome to sbt 1.11.5 (Eclipse Adoptium Java 17.0.10)
146151[info] set current project to test-project (in build file:/Users/test/project/)
147- [info] In file:/Users/test/project/
148- [info] sbt.plugins.CorePlugin: enabled in root
149- [info] sbt.plugins.IvyPlugin: enabled in root
150- [info] sbt.plugins.JvmPlugin: enabled in root
151- [info] sbt.plugins.MiniDependencyTreePlugin: enabled in root
152- [info] sbt.plugins.DependencyTreePlugin: enabled in root
153- [info] sbt.plugins.SemanticdbPlugin: enabled in root
152+ In build /Users/test/project/:
153+ Enabled plugins in root:
154+ sbt.plugins.CorePlugin
155+ sbt.plugins.DependencyTreePlugin
156+ sbt.plugins.IvyPlugin
157+ sbt.plugins.JvmPlugin
158+ Plugins that are loaded to the build but not enabled in any subprojects:
159+ sbt.plugins.MiniDependencyTreePlugin
154160|]
155161
156- -- A pathological setup that lists both modern and legacy plugins .
162+ -- A pathological build that enables both the modern and the legacy plugin .
157163sbtBothModernAndLegacy :: Text
158164sbtBothModernAndLegacy =
159165 [r |[info] welcome to sbt 1.9.7 (Eclipse Adoptium Java 11.0.21)
160- [info] In file:/Users/test/project/
161- [info] sbt.plugins.CorePlugin: enabled in root
162- [info] sbt.plugins.IvyPlugin: enabled in root
163- [info] sbt.plugins.JvmPlugin: enabled in root
164- [info] sbt.plugins.DependencyTreePlugin: enabled in root
165- [info] net.virtualvoid.sbt.graph.DependencyGraphPlugin: enabled in root
166+ [info] set current project to test-project (in build file:/Users/test/project/)
167+ In build /Users/test/project/:
168+ Enabled plugins in root:
169+ sbt.plugins.CorePlugin
170+ sbt.plugins.DependencyTreePlugin
171+ sbt.plugins.IvyPlugin
172+ sbt.plugins.JvmPlugin
173+ net.virtualvoid.sbt.graph.DependencyGraphPlugin
174+ Plugins that are loaded to the build but not enabled in any subprojects:
175+ sbt.plugins.SbtPlugin
166176|]
167177
168178sbtNoPlugins :: Text
169179sbtNoPlugins =
170180 [r |[info] welcome to sbt 1.9.7 (Eclipse Adoptium Java 11.0.21)
171- [info] loading global plugins from /Users/test/.sbt/1.0/plugins
172- [info] loading project definition from /Users/test/project/project
173- [info] loading settings for project root from build.sbt ...
174181[info] set current project to test-project (in build file:/Users/test/project/)
175- [info] In file:/Users/test/project/
176- [info] sbt.plugins.CorePlugin: enabled in root
177- [info] sbt.plugins.IvyPlugin: enabled in root
178- [info] sbt.plugins.JvmPlugin: enabled in root
182+ In build /Users/test/project/:
183+ Enabled plugins in root:
184+ sbt.plugins.CorePlugin
185+ sbt.plugins.IvyPlugin
186+ sbt.plugins.JvmPlugin
187+ Plugins that are loaded to the build but not enabled in any subprojects:
188+ sbt.plugins.SbtPlugin
179189|]
180190
181- -- User-disabled MiniDependencyTreePlugin (e.g. `disablePlugins(MiniDependencyTreePlugin)`
182- -- in build.sbt). The FQCN appears on a ": disabled in" line — detection
183- -- must reject it.
184- sbtDisabledMiniPlugin :: Text
185- sbtDisabledMiniPlugin =
186- [r |[info] welcome to sbt 1.9.7 (Eclipse Adoptium Java 11.0.21)
187- [info] In file:/Users/test/project/
188- [info] sbt.plugins.CorePlugin: enabled in root
189- [info] sbt.plugins.IvyPlugin: enabled in root
190- [info] sbt.plugins.JvmPlugin: enabled in root
191- [info] sbt.plugins.MiniDependencyTreePlugin: disabled in root
191+ -- Verbatim sbt 1.9.8 output with `disablePlugins(sbt.plugins.MiniDependencyTreePlugin)`
192+ -- on the root project. The plugin appears only in the trailing not-enabled
193+ -- section.
194+ sbt198DisabledMini :: Text
195+ sbt198DisabledMini =
196+ [r |[info] welcome to sbt 1.9.8 (Homebrew Java 24.0.1)
197+ [info] loading project definition from /private/tmp/scala3-example-project/project
198+ [info] loading settings for project root from build.sbt ...
199+ [info] set current project to scala3-example-project (in build file:/private/tmp/scala3-example-project/)
200+ In build /private/tmp/scala3-example-project/:
201+ Enabled plugins in root:
202+ sbt.plugins.CorePlugin
203+ sbt.plugins.Giter8TemplatePlugin
204+ sbt.plugins.IvyPlugin
205+ sbt.plugins.JUnitXmlReportPlugin
206+ sbt.plugins.JvmPlugin
207+ sbt.plugins.SemanticdbPlugin
208+ Plugins that are loaded to the build but not enabled in any subprojects:
209+ sbt.ScriptedPlugin
210+ sbt.plugins.MiniDependencyTreePlugin
211+ sbt.plugins.SbtPlugin
192212|]
193213
194- -- User-disabled modern DependencyTreePlugin. Routing to the uppercase task
195- -- would fail because the plugin isn't active .
196- sbtDisabledModernPlugin :: Text
197- sbtDisabledModernPlugin =
214+ -- Modern DependencyTreePlugin disabled via disablePlugins; it appears only in
215+ -- the trailing not-enabled section, so routing must not target its task .
216+ sbtDisabledModern :: Text
217+ sbtDisabledModern =
198218 [r |[info] welcome to sbt 1.11.5 (Eclipse Adoptium Java 17.0.10)
199- [info] In file:/Users/test/project/
200- [info] sbt.plugins.CorePlugin: enabled in root
201- [info] sbt.plugins.IvyPlugin: enabled in root
202- [info] sbt.plugins.JvmPlugin: enabled in root
203- [info] sbt.plugins.DependencyTreePlugin: disabled in root
219+ [info] set current project to test-project (in build file:/Users/test/project/)
220+ In build /Users/test/project/:
221+ Enabled plugins in root:
222+ sbt.plugins.CorePlugin
223+ sbt.plugins.IvyPlugin
224+ sbt.plugins.JvmPlugin
225+ Plugins that are loaded to the build but not enabled in any subprojects:
226+ sbt.plugins.DependencyTreePlugin
204227|]
0 commit comments