Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,18 @@ public final class Constants {
@Config(type = "java.lang.Boolean", defaultValue = "true")
public static final String MAVEN_CONSUMER_POM = "maven.consumer.pom";

/**
* User property for controlling consumer POM flattening behavior.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I understand correctly that this can only be controlled by a -D flag? So you cannot easily enable flattening on specific modules. I guess you could add -D to .mvn/maven.config if you wished to enable flattening on all modules in a given reactor (such as one Git repository). Has any thought been given to controlling this mode based on a flag set in the POM itself (if that is even possible)? Or as a configuration option to the install mojo, etc.?

* When set to <code>true</code> (default), consumer POMs are flattened by removing
* dependency management and keeping only direct dependencies with transitive scopes.
* When set to <code>false</code>, consumer POMs preserve dependency management
Comment on lines +468 to +470
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This says true is the default, but the code and the PR description says false is the default…?

* like parent POMs, allowing dependency management to be inherited by consumers.
*
* @since 4.1.0
*/
@Config(type = "java.lang.Boolean", defaultValue = "false")
public static final String MAVEN_CONSUMER_POM_FLATTEN = "maven.consumer.pom.flatten";

/**
* User property for controlling "maven personality". If activated Maven will behave
* like the previous major version, Maven 3.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ public static boolean consumerPom(@Nullable Map<String, ?> userProperties) {
return doGet(userProperties, Constants.MAVEN_CONSUMER_POM, !mavenMaven3Personality(userProperties));
}

/**
* Check if consumer POM flattening is enabled.
*/
public static boolean consumerPomFlatten(@Nullable Map<String, ?> userProperties) {
return doGet(userProperties, Constants.MAVEN_CONSUMER_POM_FLATTEN, false);
}

/**
* Check if build POM deployment is enabled.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.apache.maven.api.Node;
import org.apache.maven.api.PathScope;
import org.apache.maven.api.SessionData;
import org.apache.maven.api.feature.Features;
import org.apache.maven.api.model.Dependency;
import org.apache.maven.api.model.DistributionManagement;
import org.apache.maven.api.model.Model;
Expand Down Expand Up @@ -72,6 +73,15 @@ class DefaultConsumerPomBuilder implements PomBuilder {
@Override
public Model build(RepositorySystemSession session, MavenProject project, Path src) throws ModelBuilderException {
Model model = project.getModel().getDelegate();
boolean flattenEnabled = Features.consumerPomFlatten(session.getConfigProperties());

// Check if consumer POM flattening is disabled
if (!flattenEnabled) {
// When flattening is disabled, treat non-POM projects like parent POMs
// Apply only basic transformations without flattening dependency management
return buildPom(session, project, src);
}
// Default behavior: flatten the consumer POM
String packaging = model.getPackaging();
String originalPackaging = project.getOriginalModel().getPackaging();
if (POM_PACKAGING.equals(packaging)) {
Expand Down Expand Up @@ -256,6 +266,7 @@ static Model transformNonPom(Model model, MavenProject project) {
warnNotDowngraded(project);
}
model = model.withModelVersion(modelVersion);

return model;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ void partialReactorShouldResolveUsingConsumerPom() throws Exception {

// First build module a to populate project-local-repo with artifacts including consumer POM
Verifier v1 = newVerifier(testDir.getAbsolutePath());
v1.addCliArguments("clean", "package", "-X");
v1.addCliArguments("clean", "package", "-X", "-Dmaven.consumer.pom.flatten=true");
v1.setLogFileName("log-1.txt");
v1.execute();
v1.verifyErrorFreeLog();

// Now build only module b; ReactorReader should pick consumer POM from project-local-repo
Verifier v2 = newVerifier(testDir.getAbsolutePath());
v2.setLogFileName("log-2.txt");
v2.addCliArguments("clean", "compile", "-f", "b", "-X");
v2.addCliArguments("clean", "compile", "-f", "b", "-X", "-Dmaven.consumer.pom.flatten=true");
v2.execute();
v2.verifyErrorFreeLog();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ void testConsumerPomFiltersScopes() throws Exception {

Verifier verifier = newVerifier(basedir.toString());
verifier.addCliArgument("install");
verifier.addCliArgument("-Dmaven.consumer.pom.flatten=true");
verifier.execute();
verifier.verifyErrorFreeLog();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.it;

import java.io.File;
import java.util.List;

import org.apache.maven.api.Constants;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* This is a test set for dependency management override scenarios when
* consumer POM flattening is disabled (maven.consumer.pom.flatten=false).
*
* Scenario:
* - A 1.0 depends on B 1.0 and manages C to 1.2
* - B 1.0 has no dependencies
* - B 2.0 depends on C 1.1
* - D depends on A 1.0 and manages B to 2.0
*
* Question: Does D depend on C, and which version?
*
* Expected behavior when flattening is disabled: D should get C 1.2 (from A's dependency management),
* not C 1.1 (from B 2.0's dependency), because A's dependency
* management applies to D's transitive dependencies.
*
* @see <a href="https://github.com/apache/maven/issues/11346">gh-11346</a>
*/
public class MavenITgh11346DependencyManagementOverrideTest extends AbstractMavenIntegrationTestCase {

/**
* Verify that when consumer POM flattening is disabled, dependency management
* from intermediate dependencies applies to the consumer's transitive dependencies.
* This test uses -Dmaven.consumer.pom.flatten=false to enable dependency management
* inheritance from transitive dependencies.
*
* @throws Exception in case of failure
*/
@Test
public void testDependencyManagementOverride() throws Exception {
File testDir = extractResources("/gh-11346-dependency-management-override");

Verifier verifier = newVerifier(testDir.getAbsolutePath());
verifier.deleteArtifacts("org.apache.maven.its.mng.depman");
// Test with dependency manager transitivity disabled instead of consumer POM flattening
verifier.addCliArgument("-D" + Constants.MAVEN_CONSUMER_POM_FLATTEN + "=false");
verifier.addCliArgument("verify");
verifier.execute();
verifier.verifyErrorFreeLog();

// Check module D's classpath
List<String> dClasspath = verifier.loadLines("module-d/target/classpath.txt");

// D should have A 1.0
assertTrue(dClasspath.contains("module-a-1.0.jar"), "D should depend on A 1.0: " + dClasspath);

// D should have B 2.0 (managed by D)
assertTrue(dClasspath.contains("module-b-2.0.jar"), "D should depend on B 2.0 (managed by D): " + dClasspath);
assertFalse(dClasspath.contains("module-b-1.0.jar"), "D should not depend on B 1.0: " + dClasspath);

// D should have C 1.2 (from A's dependency management)
// A's dependency management of C to 1.2 should apply to D
assertTrue(
dClasspath.contains("module-c-1.2.jar"),
"D should depend on C 1.2 (A's dependency management should apply): " + dClasspath);
assertFalse(
dClasspath.contains("module-c-1.1.jar"),
"D should not depend on C 1.1 (should be managed to 1.2): " + dClasspath);
}

@Test
public void testDependencyManagementOverrideNoTransitive() throws Exception {
File testDir = extractResources("/gh-11346-dependency-management-override");

Verifier verifier = newVerifier(testDir.getAbsolutePath());
verifier.deleteArtifacts("org.apache.maven.its.mng.depman");
// Test with dependency manager transitivity disabled instead of consumer POM flattening
verifier.addCliArgument("-D" + Constants.MAVEN_CONSUMER_POM_FLATTEN + "=false");
verifier.addCliArgument("-D" + Constants.MAVEN_RESOLVER_DEPENDENCY_MANAGER_TRANSITIVITY + "=false");
verifier.addCliArgument("verify");
verifier.execute();
verifier.verifyErrorFreeLog();

// Check module D's classpath
List<String> dClasspath = verifier.loadLines("module-d/target/classpath.txt");

// D should have A 1.0
assertTrue(dClasspath.contains("module-a-1.0.jar"), "D should depend on A 1.0: " + dClasspath);

// D should have B 2.0 (managed by D)
assertTrue(dClasspath.contains("module-b-2.0.jar"), "D should depend on B 2.0 (managed by D): " + dClasspath);
assertFalse(dClasspath.contains("module-b-1.0.jar"), "D should not depend on B 1.0: " + dClasspath);

// D should have C 1.1 as the resolver is not transitive
assertFalse(
dClasspath.contains("module-c-1.2.jar"),
"D should depend on C 1.2 (A's dependency management should apply): " + dClasspath);
assertTrue(
dClasspath.contains("module-c-1.1.jar"),
"D should not depend on C 1.1 (should be managed to 1.2): " + dClasspath);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public void testWithPath() throws Exception {
verifier.setAutoclean(false);
verifier.deleteDirectory("target");
verifier.deleteArtifacts("org.apache.maven.its.mng5102");
verifier.addCliArgument("install");
verifier.addCliArguments("install", "-Dmaven.consumer.pom.flatten=true");
verifier.execute();
verifier.verifyErrorFreeLog();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public void testPublishedPoms() throws Exception {
verifier.setAutoclean(false);
verifier.addCliArgument("-Dchangelist=MNG6656");

verifier.addCliArgument("install");
verifier.addCliArguments("install", "-Dmaven.consumer.pom.flatten=true");
verifier.execute();
verifier.verifyErrorFreeLog();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void testPublishedPoms() throws Exception {

Verifier verifier = newVerifier(testDir.getAbsolutePath());
verifier.setAutoclean(false);
verifier.addCliArgument("-Dchangelist=MNG6957");
verifier.addCliArguments("-Dchangelist=MNG6957", "-Dmaven.consumer.pom.flatten=true");

verifier.addCliArgument("install");
verifier.execute();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void testNotPreserving() throws Exception {
extractResources("/mng-8414-consumer-pom-with-new-features").toPath();

Verifier verifier = newVerifier(basedir.toString(), null);
verifier.addCliArguments("package");
verifier.addCliArguments("package", "-Dmaven.consumer.pom.flatten=true");
verifier.execute();
verifier.verifyErrorFreeLog();

Expand Down Expand Up @@ -78,7 +78,7 @@ void testPreserving() throws Exception {

Verifier verifier = newVerifier(basedir.toString(), null);
verifier.setLogFileName("log-preserving.txt");
verifier.addCliArguments("-f", "pom-preserving.xml", "package");
verifier.addCliArguments("-f", "pom-preserving.xml", "package", "-Dmaven.consumer.pom.flatten=true");
verifier.execute();
verifier.verifyErrorFreeLog();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void testIt() throws Exception {
extractResources("/mng-8523-model-properties").getAbsoluteFile().toPath();

Verifier verifier = newVerifier(basedir.toString());
verifier.addCliArguments("install", "-DmavenVersion=4.0.0-rc-2");
verifier.addCliArguments("install", "-DmavenVersion=4.0.0-rc-2", "-Dmaven.consumer.pom.flatten=true");
verifier.execute();
verifier.verifyErrorFreeLog();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void testIt() throws Exception {
extractResources("/mng-8527-consumer-pom").getAbsoluteFile().toPath();

Verifier verifier = newVerifier(basedir.toString());
verifier.addCliArgument("install");
verifier.addCliArguments("install", "-Dmaven.consumer.pom.flatten=true");
verifier.execute();
verifier.verifyErrorFreeLog();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ void installDependencies() throws VerificationException, IOException {
File depsDir = new File(testDir, "deps");
Verifier deps = newVerifier(depsDir.getAbsolutePath(), false);
deps.addCliArgument("install");
deps.addCliArgument("-Dmaven.consumer.pom.flatten=true");
deps.execute();
deps.verifyErrorFreeLog();
}
Expand All @@ -71,6 +72,7 @@ public void testCompileOnlyScope() throws Exception {
Verifier verifier = newVerifier(projectDir.getAbsolutePath(), false);
verifier.addCliArgument("clean");
verifier.addCliArgument("test");
verifier.addCliArgument("-Dmaven.consumer.pom.flatten=true");
verifier.execute();
verifier.verifyErrorFreeLog();

Expand Down Expand Up @@ -102,6 +104,7 @@ public void testTestOnlyScope() throws Exception {
Verifier verifier = newVerifier(projectDir.getAbsolutePath(), false);
verifier.addCliArgument("clean");
verifier.addCliArgument("test");
verifier.addCliArgument("-Dmaven.consumer.pom.flatten=true");
verifier.execute();
verifier.verifyErrorFreeLog();

Expand Down Expand Up @@ -133,6 +136,7 @@ public void testTestRuntimeScope() throws Exception {
Verifier verifier = newVerifier(projectDir.getAbsolutePath(), false);
verifier.addCliArgument("clean");
verifier.addCliArgument("test");
verifier.addCliArgument("-Dmaven.consumer.pom.flatten=true");
verifier.execute();
verifier.verifyErrorFreeLog();

Expand Down Expand Up @@ -161,6 +165,7 @@ public void testAllNewScopesTogether() throws Exception {
Verifier verifier = newVerifier(projectDir.getAbsolutePath(), false);
verifier.addCliArgument("clean");
verifier.addCliArgument("test");
verifier.addCliArgument("-Dmaven.consumer.pom.flatten=true");
verifier.execute();
verifier.verifyErrorFreeLog();

Expand Down Expand Up @@ -193,6 +198,7 @@ public void testValidationFailureWithModelVersion40() throws Exception {
Verifier verifier = newVerifier(projectDir.getAbsolutePath(), false);
verifier.addCliArgument("clean");
verifier.addCliArgument("validate");
verifier.addCliArgument("-Dmaven.consumer.pom.flatten=true");

assertThrows(
VerificationException.class,
Expand All @@ -218,6 +224,7 @@ public void testValidationSuccessWithModelVersion41() throws Exception {
Verifier verifier = newVerifier(projectDir.getAbsolutePath(), false);
verifier.addCliArgument("clean");
verifier.addCliArgument("validate");
verifier.addCliArgument("-Dmaven.consumer.pom.flatten=true");
verifier.execute();
verifier.verifyErrorFreeLog();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.maven.its.mng.depman</groupId>
<artifactId>test</artifactId>
<version>0.1</version>
</parent>

<artifactId>module-a</artifactId>
<version>1.0</version>

<dependencyManagement>
<dependencies>
<!-- A manages C to version 1.2 -->
<dependency>
<groupId>org.apache.maven.its.mng.depman</groupId>
<artifactId>module-c</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<!-- A depends on B 1.0 -->
<dependency>
<groupId>org.apache.maven.its.mng.depman</groupId>
<artifactId>module-b</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
Loading