Skip to content

Commit fdd2b51

Browse files
brunoborgesCopilot
authored andcommitted
[#1637] Fix dependency:add routing versioned deps into dependencyManagement
The `dependency:add` goal incorrectly added a versioned dependency to the current POM's <dependencyManagement> instead of <dependencies> when the project's existing dependencies are version-less because their versions come from a BOM import (the standard maven-archetype-quickstart layout). With align=true (default), detectConventions() set useManaged=true purely because most <dependencies> were version-less, even though no parent POM existed to host the managed entry. The result was written to the current POM's <dependencyManagement>, which contradicts the documented behavior of the `align` parameter ("add managed dependency to parent POM") and means the dependency was never actually added to the project. The auto-detected useManaged convention now only applies when a separate parent POM exists to host the managed dependency. For a single/leaf POM a versioned add goes to <dependencies>. Explicit -Dmanaged=true is unchanged. Adds an integration test (add-dependency/bom-import) reproducing the case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent ff77e43 commit fdd2b51

4 files changed

Lines changed: 116 additions & 6 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
invoker.goals = ${project.groupId}:${project.artifactId}:${project.version}:add -Dgav=org.apache.maven.its.dependency:a1:1.0.0
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<!--
4+
~ Licensed to the Apache Software Foundation (ASF) under one
5+
~ or more contributor license agreements. See the NOTICE file
6+
~ distributed with this work for additional information
7+
~ regarding copyright ownership. The ASF licenses this file
8+
~ to you under the Apache License, Version 2.0 (the
9+
~ "License"); you may not use this file except in compliance
10+
~ with the License. You may obtain a copy of the License at
11+
~
12+
~ http://www.apache.org/licenses/LICENSE-2.0
13+
~
14+
~ Unless required by applicable law or agreed to in writing,
15+
~ software distributed under the License is distributed on an
16+
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
~ KIND, either express or implied. See the License for the
18+
~ specific language governing permissions and limitations
19+
~ under the License.
20+
-->
21+
22+
<project xmlns="http://maven.apache.org/POM/4.0.0"
23+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
24+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
25+
<modelVersion>4.0.0</modelVersion>
26+
<groupId>test</groupId>
27+
<artifactId>add-dependency-bom-import</artifactId>
28+
<version>1.0-SNAPSHOT</version>
29+
30+
<dependencyManagement>
31+
<dependencies>
32+
<dependency>
33+
<groupId>org.junit</groupId>
34+
<artifactId>junit-bom</artifactId>
35+
<version>5.11.0</version>
36+
<type>pom</type>
37+
<scope>import</scope>
38+
</dependency>
39+
</dependencies>
40+
</dependencyManagement>
41+
42+
<dependencies>
43+
<dependency>
44+
<groupId>org.junit.jupiter</groupId>
45+
<artifactId>junit-jupiter-api</artifactId>
46+
<scope>test</scope>
47+
</dependency>
48+
<dependency>
49+
<groupId>org.junit.jupiter</groupId>
50+
<artifactId>junit-jupiter-params</artifactId>
51+
<scope>test</scope>
52+
</dependency>
53+
</dependencies>
54+
</project>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
// A single, leaf POM whose existing dependencies are version-less because their
21+
// versions come from a BOM import in <dependencyManagement>. A versioned add must
22+
// land in <dependencies> (not be redirected into this POM's <dependencyManagement>).
23+
File pom = new File(basedir, "pom.xml")
24+
assert pom.exists()
25+
def xml = new groovy.xml.XmlSlurper().parseText(pom.text)
26+
27+
def dep = xml.dependencies.dependency.find { it.artifactId.text() == 'a1' }
28+
assert dep != null : "a1 should be added to <dependencies>"
29+
assert dep.groupId.text() == 'org.apache.maven.its.dependency'
30+
assert dep.version.text() == '1.0.0'
31+
32+
def managed = xml.dependencyManagement.dependencies.dependency.find { it.artifactId.text() == 'a1' }
33+
assert managed == null || managed.size() == 0 : "a1 must NOT be added to <dependencyManagement>"

src/main/java/org/apache/maven/plugins/dependency/AddDependencyMojo.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -642,20 +642,25 @@ private Conventions detectConventions(MavenProject project) throws MojoExecution
642642
try {
643643
PomEditor editor = loadPomEditor(pomFile);
644644

645+
// Find the parent POM that declares <dependencyManagement>, if any.
646+
conv.managedPomFile = findManagedDepsPom(project);
647+
645648
// Analyze managed dependency usage: count deps with/without version
646649
long totalDeps = getDependencyCount(editor, false);
647650
List<String> depVersions = getDependencyVersions(editor, false);
648651
long depsWithVersion = depVersions.size();
649652

650-
if (totalDeps > 0 && depsWithVersion < totalDeps / 2.0) {
651-
// Majority of deps are version-less → use managed deps
653+
// Only treat version-less dependencies as a "managed" convention when there is a
654+
// separate parent POM to host the managed dependency. Otherwise (e.g. a single,
655+
// leaf POM whose dependency versions come from a local BOM import), a versioned add
656+
// belongs in <dependencies>, not in this POM's <dependencyManagement>.
657+
if (conv.managedPomFile != null && totalDeps > 0 && depsWithVersion < totalDeps / 2.0) {
658+
// Majority of deps are version-less and a parent manages versions → use managed deps
652659
conv.useManaged = true;
653-
getLog().debug("Convention detected: majority of dependencies are version-less (useManaged=true)");
660+
getLog().debug("Convention detected: majority of dependencies are version-less"
661+
+ " and a parent POM manages versions (useManaged=true)");
654662
}
655663

656-
// Find the POM that has <dependencyManagement>
657-
conv.managedPomFile = findManagedDepsPom(project);
658-
659664
// Analyze property patterns from child POM versions
660665
List<String> allVersions = new java.util.ArrayList<>(depVersions);
661666
allVersions.addAll(getDependencyVersions(editor, true));

0 commit comments

Comments
 (0)