You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/08/31 02:33:39 UTC

(maven) 02/05: Fix consumer POM dependency resolution for packaging-activated profiles

This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch backport/12744-to-maven-4.0.x
in repository https://gitbox.apache.org/repos/asf/maven.git

commit 77165a79b616724ad15428f6034fb1d3a56c8a37
Author: Hitesh <hi...@saividya.ac.in>
AuthorDate: Thu Aug 13 21:35:53 2026 +0530

    Fix consumer POM dependency resolution for packaging-activated profiles
    
    - Inline packaging-activated profiles during transformPom for non-flattened builds
    
    - Drop profiles activated by non-matching packaging entirely
    
    - Update ConsumerPomBuilderTest to enable flattening and assert on dropped profiles
    
    Signed-off-by: Hitesh <hi...@saividya.ac.in>
---
 .../impl/DefaultConsumerPomBuilder.java            | 37 ++++++------
 .../impl/ConsumerPomBuilderTest.java               | 67 ++++++++++++++++------
 .../resources/consumer/packaging-profiles/pom.xml  | 62 ++++++++++++++++++++
 3 files changed, 130 insertions(+), 36 deletions(-)

diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java b/impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java
index 77facf964c..cdd6e374ca 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java
@@ -470,6 +470,10 @@ private static Model transformBom(Model model, MavenProject project) {
 
     static Model transformPom(Model model, MavenProject project) {
         boolean preserveModelVersion = model.isPreserveModelVersion();
+        String packaging = model.getPackaging();
+
+        // Inline packaging-activated profiles into the model
+        model = inlinePackagingActivatedProfiles(model, packaging);
 
         // raw to consumer transform
         model = model.withRoot(false).withModules(null).withSubprojects(null);
@@ -533,24 +537,23 @@ static Model inlinePackagingActivatedProfiles(Model model, String packaging) {
             Activation activation = profile.getActivation();
             if (activation != null && activation.getPackaging() != null) {
                 if (Objects.equals(activation.getPackaging(), packaging)) {
-                    // Packaging matches — inline profile content into the model
-                    additionalDeps.addAll(profile.getDependencies());
-                    if (profile.getDependencyManagement() != null) {
-                        additionalManagedDeps.addAll(
-                                profile.getDependencyManagement().getDependencies());
-                    }
-                    additionalRepos.addAll(profile.getRepositories());
-
-                    // Check if the profile has other activation conditions besides packaging
                     Activation strippedActivation = stripPackagingActivation(activation);
                     if (strippedActivation != null) {
                         // Keep the profile but remove the packaging activation part
+                        // Do not inline its contents since it has other activation conditions
                         remainingProfiles.add(profile.withActivation(strippedActivation));
+                    } else {
+                        // Packaging is the ONLY condition.
+                        // Inline profile content into the model
+                        additionalDeps.addAll(profile.getDependencies());
+                        if (profile.getDependencyManagement() != null) {
+                            additionalManagedDeps.addAll(
+                                    profile.getDependencyManagement().getDependencies());
+                        }
+                        additionalRepos.addAll(profile.getRepositories());
                     }
-                    // else: profile only had packaging activation, fully inlined, drop it
                 } else {
-                    // Packaging does not match — keep the profile as-is
-                    remainingProfiles.add(profile);
+                    // Packaging does not match — drop the profile entirely
                 }
             } else {
                 // No packaging activation — keep the profile as-is
@@ -560,6 +563,7 @@ static Model inlinePackagingActivatedProfiles(Model model, String packaging) {
 
         // Merge additional dependencies into the model
         if (!additionalDeps.isEmpty()) {
+            additionalDeps.removeIf(DefaultConsumerPomBuilder::hasDependencyScope);
             List<Dependency> allDeps = new ArrayList<>(model.getDependencies());
             allDeps.addAll(additionalDeps);
             model = model.withDependencies(allDeps);
@@ -568,9 +572,7 @@ static Model inlinePackagingActivatedProfiles(Model model, String packaging) {
         // Merge additional managed dependencies into the model
         if (!additionalManagedDeps.isEmpty()) {
             DependencyManagement dm = model.getDependencyManagement();
-            List<Dependency> allManagedDeps = dm != null
-                    ? new ArrayList<>(dm.getDependencies())
-                    : new ArrayList<>();
+            List<Dependency> allManagedDeps = dm != null ? new ArrayList<>(dm.getDependencies()) : new ArrayList<>();
             allManagedDeps.addAll(additionalManagedDeps);
             model = model.withDependencyManagement(
                     (dm != null ? dm : DependencyManagement.newInstance()).withDependencies(allManagedDeps));
@@ -591,9 +593,8 @@ static Model inlinePackagingActivatedProfiles(Model model, String packaging) {
      * or {@code null} if packaging was the only activation condition.
      */
     private static Activation stripPackagingActivation(Activation activation) {
-        Activation stripped = Activation.newBuilder(activation, true)
-                .packaging(null)
-                .build();
+        Activation stripped =
+                Activation.newBuilder(activation, true).packaging(null).build();
         // Check if the remaining activation has any other conditions
         if (!stripped.isActiveByDefault()
                 && stripped.getJdk() == null
diff --git a/impl/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomBuilderTest.java b/impl/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomBuilderTest.java
index 82646d81ba..521928da60 100644
--- a/impl/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomBuilderTest.java
+++ b/impl/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomBuilderTest.java
@@ -33,7 +33,6 @@
 import org.apache.maven.api.SessionData;
 import org.apache.maven.api.model.Activation;
 import org.apache.maven.api.model.Dependency;
-import org.apache.maven.api.model.DependencyManagement;
 import org.apache.maven.api.model.Model;
 import org.apache.maven.api.model.Profile;
 import org.apache.maven.api.model.Scm;
@@ -141,6 +140,32 @@ void testTrivialConsumer() throws Exception {
         assertNotNull(model.getDependencies());
     }
 
+    @Test
+    void testPackagingActivatedProfiles() throws Exception {
+        MavenExecutionRequest request = setRootDirectory("packaging-profiles");
+        request.getUserProperties().setProperty("maven.consumer.pom.flatten", "true");
+        java.nio.file.Path file = java.nio.file.Paths.get("src/test/resources/consumer/packaging-profiles/pom.xml");
+
+        org.apache.maven.project.MavenProject project = getEffectiveModel(file);
+
+        org.apache.maven.api.model.Model model =
+                builder.build(session, project, org.apache.maven.api.services.Sources.buildSource(file));
+
+        assertNotNull(model);
+
+        assertEquals(1, model.getProfiles().size());
+        org.apache.maven.api.model.Profile mixedProfile = model.getProfiles().get(0);
+        assertEquals("mixed-profile", mixedProfile.getId());
+        assertNotNull(mixedProfile.getActivation());
+        assertNull(mixedProfile.getActivation().getPackaging());
+        assertNotNull(mixedProfile.getActivation().getProperty());
+        assertEquals("foo", mixedProfile.getActivation().getProperty().getName());
+
+        assertNotNull(model.getDependencies());
+        assertEquals(1, model.getDependencies().size());
+        assertEquals("slf4j-api", model.getDependencies().get(0).getArtifactId());
+    }
+
     @Test
     void testSimpleConsumer() throws Exception {
         MavenExecutionRequest request = setRootDirectory("simple");
@@ -393,45 +418,51 @@ void testConsumerPomSessionPropertiesOverrideProfileProperties() throws Exceptio
 
     @Test
     void testInlinePackagingActivatedProfiles() {
-        Dependency dep1 = Dependency.newBuilder().groupId("g").artifactId("a1").version("1").build();
-        Dependency dep2 = Dependency.newBuilder().groupId("g").artifactId("a2").version("2").build();
-        
+        Dependency dep1 = Dependency.newBuilder()
+                .groupId("g")
+                .artifactId("a1")
+                .version("1")
+                .build();
+        Dependency dep2 = Dependency.newBuilder()
+                .groupId("g")
+                .artifactId("a2")
+                .version("2")
+                .build();
+
         Profile profileMatching = Profile.newBuilder()
                 .id("matching")
                 .activation(Activation.newBuilder().packaging("jar").build())
                 .dependencies(List.of(dep1))
                 .build();
-                
+
         Profile profileNotMatching = Profile.newBuilder()
                 .id("not-matching")
                 .activation(Activation.newBuilder().packaging("war").build())
                 .dependencies(List.of(dep2))
                 .build();
-                
+
         Profile profileMixed = Profile.newBuilder()
                 .id("mixed")
                 .activation(Activation.newBuilder().packaging("jar").jdk("11").build())
                 .dependencies(List.of(dep2))
                 .build();
-                
+
         Model model = Model.newBuilder()
                 .packaging("jar")
                 .profiles(List.of(profileMatching, profileNotMatching, profileMixed))
                 .build();
-                
+
         Model transformed = DefaultConsumerPomBuilder.inlinePackagingActivatedProfiles(model, "jar");
-        
+
         // matching profile should be removed and its deps added to model
-        // not-matching profile should be kept intact
+        // not-matching profile should be dropped entirely since its packaging condition can never be met
         // mixed profile should be kept but packaging activation stripped
-        assertEquals(2, transformed.getProfiles().size());
-        assertEquals("not-matching", transformed.getProfiles().get(0).getId());
-        assertEquals("war", transformed.getProfiles().get(0).getActivation().getPackaging());
-        
-        assertEquals("mixed", transformed.getProfiles().get(1).getId());
-        assertNull(transformed.getProfiles().get(1).getActivation().getPackaging());
-        assertEquals("11", transformed.getProfiles().get(1).getActivation().getJdk());
-        
+        assertEquals(1, transformed.getProfiles().size());
+
+        assertEquals("mixed", transformed.getProfiles().get(0).getId());
+        assertNull(transformed.getProfiles().get(0).getActivation().getPackaging());
+        assertEquals("11", transformed.getProfiles().get(0).getActivation().getJdk());
+
         assertEquals(1, transformed.getDependencies().size());
         assertEquals("a1", transformed.getDependencies().get(0).getArtifactId());
     }
diff --git a/impl/maven-core/src/test/resources/consumer/packaging-profiles/pom.xml b/impl/maven-core/src/test/resources/consumer/packaging-profiles/pom.xml
new file mode 100644
index 0000000000..44932fb1b4
--- /dev/null
+++ b/impl/maven-core/src/test/resources/consumer/packaging-profiles/pom.xml
@@ -0,0 +1,62 @@
+<project xmlns="http://maven.apache.org/POM/4.1.0">
+  <modelVersion>4.1.0</modelVersion>
+  <groupId>org.my.group</groupId>
+  <artifactId>packaging-profiles-test</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <profiles>
+    <profile>
+      <id>matching-profile</id>
+      <activation>
+        <packaging>jar</packaging>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-api</artifactId>
+          <version>2.0.0</version>
+          <!-- Using compile scope since api scope does not exist in this branch -->
+          <scope>compile</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-simple</artifactId>
+          <version>2.0.0</version>
+          <scope>test</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+    <profile>
+      <id>non-matching-profile</id>
+      <activation>
+        <packaging>war</packaging>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.junit.jupiter</groupId>
+          <artifactId>junit-jupiter-api</artifactId>
+          <version>5.9.0</version>
+          <scope>compile</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+    <profile>
+      <id>mixed-profile</id>
+      <activation>
+        <packaging>jar</packaging>
+        <property>
+          <name>foo</name>
+        </property>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.commons</groupId>
+          <artifactId>commons-lang3</artifactId>
+          <version>3.12.0</version>
+          <scope>compile</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+  </profiles>
+</project>