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 138fc8c11d..65e771e06f 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 @@ -44,6 +44,8 @@ import org.apache.maven.internal.impl.InternalSession; import org.apache.maven.model.v4.MavenModelVersion; import org.apache.maven.project.MavenProject; import org.eclipse.aether.RepositorySystemSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @Named class DefaultConsumerPomBuilder implements ConsumerPomBuilder { @@ -51,6 +53,8 @@ class DefaultConsumerPomBuilder implements ConsumerPomBuilder { public static final String POM_PACKAGING = "pom"; + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultConsumerPomBuilder.class); + private final LifecycleBindingsInjector lifecycleBindingsInjector; @Inject @@ -103,6 +107,7 @@ class DefaultConsumerPomBuilder implements ConsumerPomBuilder { static Model transform(Model model, MavenProject project) { String packaging = model.getPackaging(); + boolean preserveModelVersion = model.isPreserveModelVersion(); if (POM_PACKAGING.equals(packaging)) { // raw to consumer transform model = model.withRoot(false).withModules(null).withSubprojects(null); @@ -110,7 +115,7 @@ class DefaultConsumerPomBuilder implements ConsumerPomBuilder { model = model.withParent(model.getParent().withRelativePath(null)); } - if (!model.isPreserveModelVersion()) { + if (!preserveModelVersion) { model = model.withPreserveModelVersion(false); String modelVersion = new MavenModelVersion().getModelVersion(model); model = model.withModelVersion(modelVersion); @@ -137,6 +142,9 @@ class DefaultConsumerPomBuilder implements ConsumerPomBuilder { model = builder.build(); String modelVersion = new MavenModelVersion().getModelVersion(model); + if (!ModelBuilder.MODEL_VERSION_4_0_0.equals(modelVersion) && !preserveModelVersion) { + warnNotDowngraded(project); + } model = model.withModelVersion(modelVersion); } else { Model.Builder builder = prune( @@ -150,11 +158,22 @@ class DefaultConsumerPomBuilder implements ConsumerPomBuilder { model = builder.build(); String modelVersion = new MavenModelVersion().getModelVersion(model); + if (!ModelBuilder.MODEL_VERSION_4_0_0.equals(modelVersion) && !preserveModelVersion) { + warnNotDowngraded(project); + } model = model.withModelVersion(modelVersion); } return model; } + static void warnNotDowngraded(MavenProject project) { + LOGGER.warn("The consumer POM for " + project.getId() + " cannot be downgraded to 4.0.0. " + + "If you intent your build to be consumed with Maven 3 projects, you need to remove " + + "the features that request a newer model version. If you're fine with having the " + + "consumer POM not consumable with Maven 3, add the `preserve.model.version='true'` " + + "attribute on the element of your POM."); + } + private static List prune(List profiles) { return profiles.stream() .map(p -> { diff --git a/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng8414ConsumerPomWithNewFeaturesTest.java b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng8414ConsumerPomWithNewFeaturesTest.java new file mode 100644 index 0000000000..c81df8c0d6 --- /dev/null +++ b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng8414ConsumerPomWithNewFeaturesTest.java @@ -0,0 +1,103 @@ +/* + * 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.Reader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.apache.maven.api.model.Model; +import org.apache.maven.model.v4.MavenStaxReader; +import org.junit.jupiter.api.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * This is a test set for MNG-8414. + */ +class MavenITmng8414ConsumerPomWithNewFeaturesTest extends AbstractMavenIntegrationTestCase { + + MavenITmng8414ConsumerPomWithNewFeaturesTest() { + super("[4.0.0-rc-2,)"); + } + + /** + * Verify behavior of the consumer POM when using a feature that require a newer model. + */ + @Test + void testNotPreserving() throws Exception { + Path basedir = + extractResources("/mng-8414-consumer-pom-with-new-features").toPath(); + + Verifier verifier = newVerifier(basedir.toString(), null); + verifier.addCliArguments("package"); + verifier.execute(); + verifier.verifyErrorFreeLog(); + + verifier.verifyTextInLog( + "The consumer POM for org.apache.maven.its:mng-8414:jar:1.0.0-SNAPSHOT cannot be downgraded to 4.0.0."); + + Path consumerPom = basedir.resolve(Paths.get( + "target", + "project-local-repo", + "org.apache.maven.its", + "mng-8414", + "1.0.0-SNAPSHOT", + "mng-8414-1.0.0-SNAPSHOT-consumer.pom")); + assertTrue(Files.exists(consumerPom)); + Model consumerPomModel; + try (Reader r = Files.newBufferedReader(consumerPom)) { + consumerPomModel = new MavenStaxReader().read(r); + } + assertEquals("4.1.0", consumerPomModel.getModelVersion()); + } + + /** + * Verify behavior of the consumer POM when using a feature that require a newer model. + */ + @Test + void testPreserving() throws Exception { + Path basedir = + extractResources("/mng-8414-consumer-pom-with-new-features").toPath(); + + Verifier verifier = newVerifier(basedir.toString(), null); + verifier.setLogFileName("log-preserving.txt"); + verifier.addCliArguments("-f", "pom-preserving.xml", "package"); + verifier.execute(); + verifier.verifyErrorFreeLog(); + + verifier.verifyTextNotInLog("cannot be downgraded to 4.0.0."); + + Path consumerPom = basedir.resolve(Paths.get( + "target", + "project-local-repo", + "org.apache.maven.its", + "mng-8414-preserving", + "1.0.0-SNAPSHOT", + "mng-8414-preserving-1.0.0-SNAPSHOT-consumer.pom")); + assertTrue(Files.exists(consumerPom)); + Model consumerPomModel; + try (Reader r = Files.newBufferedReader(consumerPom)) { + consumerPomModel = new MavenStaxReader().read(r); + } + assertEquals("4.1.0", consumerPomModel.getModelVersion()); + } +} diff --git a/its/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java b/its/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java index 87b599b69f..4f26dab735 100644 --- a/its/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java +++ b/its/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java @@ -100,6 +100,7 @@ public class TestSuiteOrdering implements ClassOrderer { * the tests are to finishing. Newer tests are also more likely to fail, so this is * a fail fast technique as well. */ + suite.addTestSuite(MavenITmng8414ConsumerPomWithNewFeaturesTest.class); suite.addTestSuite(MavenITmng8245BeforePhaseCliTest.class); suite.addTestSuite(MavenITmng8244PhaseAllTest.class); suite.addTestSuite(MavenITmng8421MavenEncryptionTest.class); diff --git a/its/core-it-suite/src/test/resources/mng-8414-consumer-pom-with-new-features/pom-preserving.xml b/its/core-it-suite/src/test/resources/mng-8414-consumer-pom-with-new-features/pom-preserving.xml new file mode 100644 index 0000000000..d4d28e6429 --- /dev/null +++ b/its/core-it-suite/src/test/resources/mng-8414-consumer-pom-with-new-features/pom-preserving.xml @@ -0,0 +1,18 @@ + + + + org.apache.maven.its + mng-8414-preserving + 1.0.0-SNAPSHOT + + + + my-profile + + true + + + + diff --git a/its/core-it-suite/src/test/resources/mng-8414-consumer-pom-with-new-features/pom.xml b/its/core-it-suite/src/test/resources/mng-8414-consumer-pom-with-new-features/pom.xml new file mode 100644 index 0000000000..54dd2c4894 --- /dev/null +++ b/its/core-it-suite/src/test/resources/mng-8414-consumer-pom-with-new-features/pom.xml @@ -0,0 +1,16 @@ + + + + org.apache.maven.its + mng-8414 + 1.0.0-SNAPSHOT + + + + my-profile + + true + + + +