Merge pull request #120 from eric-milles/IVY-1667

IVY-1667: `makepom`: check output lines for `dependencyManagement` element
This commit is contained in:
Maarten Coene 2026-06-16 00:06:25 +02:00 committed by GitHub
commit f72d589709
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 313 additions and 68 deletions

View File

@ -72,22 +72,18 @@ public final class PomModuleDescriptorWriter {
throws IOException { throws IOException {
LineNumberReader in; LineNumberReader in;
if (options.getTemplate() == null) { if (options.getTemplate() == null) {
in = new LineNumberReader(new InputStreamReader( in = new LineNumberReader(new InputStreamReader(PomModuleDescriptorWriter.class.getResourceAsStream("pom.template")));
PomModuleDescriptorWriter.class.getResourceAsStream("pom.template")));
} else { } else {
in = new LineNumberReader(new InputStreamReader(new FileInputStream( in = new LineNumberReader(new InputStreamReader(new FileInputStream(options.getTemplate())));
options.getTemplate())));
} }
if (output.getParentFile() != null) { if (output.getParentFile() != null) {
output.getParentFile().mkdirs(); output.getParentFile().mkdirs();
} }
PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(output),
StandardCharsets.UTF_8)); try (PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(output), StandardCharsets.UTF_8))) {
try {
IvySettings settings = IvyContext.getContext().getSettings(); IvySettings settings = IvyContext.getContext().getSettings();
IvyVariableContainer variables = new IvyVariableContainerWrapper( IvyVariableContainer variables = new IvyVariableContainerWrapper(settings.getVariableContainer());
settings.getVariableContainer());
variables.setVariable("ivy.pom.license", SKIP_LINE, true); variables.setVariable("ivy.pom.license", SKIP_LINE, true);
variables.setVariable("ivy.pom.header", SKIP_LINE, true); variables.setVariable("ivy.pom.header", SKIP_LINE, true);
@ -103,53 +99,56 @@ public final class PomModuleDescriptorWriter {
variables.setVariable("ivy.pom.license", options.getLicenseHeader(), true); variables.setVariable("ivy.pom.license", options.getLicenseHeader(), true);
} }
if (options.isPrintIvyInfo()) { if (options.isPrintIvyInfo()) {
String header = "<!--\n" + " Apache Maven 2 POM generated by Apache Ivy\n" String header
+ " " + Ivy.getIvyHomeURL() + "\n" + " Apache Ivy version: " = "<!--\n" // TODO: replace \n with lineSeparator()
+ Ivy.getIvyVersion() + " " + Ivy.getIvyDate() + "\n" + "-->"; + " Apache Maven 2 POM generated by Apache Ivy\n"
+ " " + Ivy.getIvyHomeURL() + "\n"
+ " Apache Ivy version: " + Ivy.getIvyVersion() + " " + Ivy.getIvyDate() + "\n"
+ "-->";
variables.setVariable("ivy.pom.header", header, true); variables.setVariable("ivy.pom.header", header, true);
} }
setModuleVariables(md, variables, options); setModuleVariables(md, variables, options);
boolean dependencyManagement = false;
boolean dependenciesPrinted = false; boolean dependenciesPrinted = false;
int lastIndent = 0; int lastIndent = 0;
int indent = 0; int indent = 0;
String line = in.readLine(); String line;
while (line != null) { while ((line = in.readLine()) != null) {
line = IvyPatternHelper.substituteVariables(line, variables); line = IvyPatternHelper.substituteVariables(line, variables);
if (line.contains(SKIP_LINE)) { if (line.contains(SKIP_LINE)) {
// skip this line // skip this line
line = in.readLine();
continue; continue;
} }
if (line.trim().isEmpty()) { if (!line.trim().isEmpty()) {
// empty line lastIndent = indent;
out.println(line); indent = line.indexOf('<');
line = in.readLine();
continue; if (line.contains("<dependencyManagement>")) {
dependencyManagement = true;
}
if (line.contains("</dependencyManagement>")) {
dependencyManagement = false;
}
if (line.contains("</dependencies>") && !dependenciesPrinted && !dependencyManagement) {
printDependencies(md, out, options, indent, false);
dependenciesPrinted = true;
}
if (line.contains("</project>") && !dependenciesPrinted) {
printDependencies(md, out, options, lastIndent, true);
dependenciesPrinted = true;
}
} }
lastIndent = indent;
indent = line.indexOf('<');
if (!dependenciesPrinted && line.contains("</dependencies>")) {
printDependencies(md, out, options, indent, false);
dependenciesPrinted = true;
}
if (!dependenciesPrinted && line.contains("</project>")) {
printDependencies(md, out, options, lastIndent, true);
dependenciesPrinted = true;
}
out.println(line); out.println(line);
line = in.readLine();
} }
} finally { } finally {
in.close(); in.close();
out.close();
} }
} }

View File

@ -15,15 +15,10 @@
* limitations under the License. * limitations under the License.
* *
*/ */
package org.apache.ivy.core.module.descriptor; package org.apache.ivy.core.module.descriptor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.File; import java.io.File;
import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -32,59 +27,61 @@ import javax.xml.xpath.XPathConstants;
import org.apache.ivy.TestHelper; import org.apache.ivy.TestHelper;
import org.apache.ivy.ant.IvyMakePom; import org.apache.ivy.ant.IvyMakePom;
import org.apache.ivy.util.TestXmlHelper; import org.apache.ivy.util.TestXmlHelper;
import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;
import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.apache.commons.io.FileUtils.writeLines;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/** /**
* Tests {@link IvyMakePom} * Tests {@link IvyMakePom}.
*/ */
public class IvyMakePomTest { public class IvyMakePomTest {
private Project project; private Project project = TestHelper.newProject();
@Rule @Rule
public TemporaryFolder workdir = new TemporaryFolder(); public TemporaryFolder workdir = new TemporaryFolder();
@Before
public void beforeTest() {
this.project = TestHelper.newProject();
}
/** /**
* Test case for IVY-1528. An Ivy file containing a <code>classifier</code> extra attribute in * Test case for <a href="https://issues.apache.org/jira/browse/IVY-1528">IVY-1528</a>.
* its dependency, must retain the <code>classifier</code> in the generated POM when converted * <p>
* to a POM file through {@link IvyMakePom}. * An Ivy file containing a <code>classifier</code> extra attribute in its
* * dependency, must retain the <code>classifier</code> in the generated POM
* @throws Exception if something goes wrong * when converted to a POM file through {@link IvyMakePom}.
* @see <a href="https://issues.apache.org/jira/browse/IVY-1528">IVY-1528</a>
*/ */
@Test @Test
public void testClassifier() throws Exception { public void testClassifier() throws Exception {
final File ivyFile = new File(IvyMakePomTest.class.getResource("ivy-to-pom-classifier.xml").toURI()); File ivyFile = new File(IvyMakePomTest.class.getResource("ivy-to-pom-classifier.xml").toURI());
assertTrue(ivyFile + " is either missing or not a file", ivyFile.isFile()); assertTrue(ivyFile + " is either missing or not a file", ivyFile.isFile());
final IvyMakePom makepom = new IvyMakePom(); File pomFile = workdir.newFile("test-ivy-to-pom-classifier.pom");
makepom.setProject(project);
final File generatedPomFile = workdir.newFile("test-ivy-to-pom-classifier.pom");
makepom.setPomFile(generatedPomFile);
makepom.setIvyFile(ivyFile);
// run the task
makepom.execute();
// read the generated pom IvyMakePom task = new IvyMakePom();
final NodeList dependencies = (NodeList) TestXmlHelper.evaluateXPathExpr(generatedPomFile, "/project/dependencies/dependency", XPathConstants.NODESET); task.setIvyFile(ivyFile);
task.setPomFile(pomFile);
task.setProject(project);
task.execute();
NodeList dependencies = (NodeList) TestXmlHelper.evaluateXPathExpr(pomFile, "/project/dependencies/dependency", XPathConstants.NODESET);
assertNotNull("Dependencies element wasn't found in the generated POM file", dependencies); assertNotNull("Dependencies element wasn't found in the generated POM file", dependencies);
assertEquals("Unexpected number of dependencies in the generated POM file", 2, dependencies.getLength()); assertEquals("Unexpected number of dependencies in the generated POM file", 2, dependencies.getLength());
final Set<String> expectedPomArtifactIds = new HashSet<>(); Set<String> expectedPomArtifactIds = new HashSet<>();
expectedPomArtifactIds.add("foo"); expectedPomArtifactIds.add("foo");
expectedPomArtifactIds.add("bar"); expectedPomArtifactIds.add("bar");
for (int i = 0; i < dependencies.getLength(); i++) { for (int i = 0; i < dependencies.getLength(); i++) {
final PomDependency pomDependency = PomDependency.parse(dependencies.item(i)); PomDependency pomDependency = PomDependency.parse(dependencies.item(i));
assertNotNull("Dependency generated was null", pomDependency); assertNotNull("Dependency generated was null", pomDependency);
assertTrue("Unexpected dependency " + pomDependency, expectedPomArtifactIds.contains(pomDependency.artifactId)); assertTrue("Unexpected dependency " + pomDependency, expectedPomArtifactIds.contains(pomDependency.artifactId));
// we no longer expect this, so remove it // we no longer expect this, so remove it
@ -103,6 +100,255 @@ public class IvyMakePomTest {
assertTrue("Some expected dependencies " + expectedPomArtifactIds + " were not found in the generated POM file", expectedPomArtifactIds.isEmpty()); assertTrue("Some expected dependencies " + expectedPomArtifactIds + " were not found in the generated POM file", expectedPomArtifactIds.isEmpty());
} }
@Test
public void testMakePomWithTemplate() throws Exception {
File ivyFile = workdir.newFile("ivy.xml");
writeLines(ivyFile, "UTF-8", Arrays.asList(
"<ivy-module version='2.0'>",
" <info module='name' organisation='org' revision='1.0.0-SNAPSHOT' />",
" <configurations>",
" <conf name='default' />",
" </configurations>",
" <dependencies defaultconf='default' defaultconfmapping='*->master,runtime()'>",
" <dependency org='org.springframework' name='spring-aop' rev='6.2.9' />",
" </dependencies>",
"</ivy-module>"
));
File pomFile = workdir.newFile("ivy.pom");
File templateFile = workdir.newFile("the.pom");
writeLines(templateFile, "UTF-8", Arrays.asList(
"<project>",
" <groupId>${ivy.pom.groupId}</groupId>",
" <artifactId>${ivy.pom.artifactId}</artifactId>",
" <version>${ivy.pom.version}</version>",
" <dependencies>",
" <dependency>",
" <groupId>org.springframework</groupId>",
" <artifactId>spring-core</artifactId>",
" <version>6.2.9</version>",
" <scope>compile</scope>",
" </dependency>",
" </dependencies>",
"</project>"
));
IvyMakePom task = new IvyMakePom();
task.setIvyFile(ivyFile);
task.setPomFile(pomFile);
task.setPrintIvyInfo(false);
task.setProject(project);
task.setTemplateFile(templateFile);
IvyMakePom.Mapping mapping = task.createMapping();
mapping.setConf("default");
mapping.setScope("compile");
task.execute();
String[] expect = {
"<project>",
" <groupId>org</groupId>",
" <artifactId>name</artifactId>",
" <version>1.0.0-SNAPSHOT</version>",
" <dependencies>",
" <dependency>",
" <groupId>org.springframework</groupId>",
" <artifactId>spring-core</artifactId>",
" <version>6.2.9</version>",
" <scope>compile</scope>",
" </dependency>",
" <dependency>",
" <groupId>org.springframework</groupId>",
" <artifactId>spring-aop</artifactId>",
" <version>6.2.9</version>",
" <scope>compile</scope>",
" </dependency>",
" </dependencies>",
"</project>",
""
};
assertEquals(String.join(System.lineSeparator(), expect), readFileToString(pomFile, "UTF-8"));
}
/**
* Test case for <a href="https://issues.apache.org/jira/browse/IVY-1667">IVY-1667</a>.
*/
@Test
public void testMakePomWithTemplate1667() throws Exception {
File ivyFile = workdir.newFile("ivy.xml");
writeLines(ivyFile, "UTF-8", Arrays.asList(
"<ivy-module version='2.0'>",
" <info module='name' organisation='org' revision='1.0.0-SNAPSHOT' />",
" <configurations>",
" <conf name='default' />",
" </configurations>",
" <dependencies defaultconf='default' defaultconfmapping='*->master,runtime()'>",
" <dependency org='org.springframework' name='spring-aop' rev='6.2.9' />",
" </dependencies>",
"</ivy-module>"
));
File pomFile = workdir.newFile("ivy.pom");
File templateFile = workdir.newFile("the.pom");
writeLines(templateFile, "UTF-8", Arrays.asList(
"<project>",
" <groupId>${ivy.pom.groupId}</groupId>",
" <artifactId>${ivy.pom.artifactId}</artifactId>",
" <version>${ivy.pom.version}</version>",
" <dependencyManagement>",
" <dependencies>",
" <dependency>",
" <groupId>org.aspectj</groupId>",
" <artifactId>aspectjrt</artifactId>",
" <version>1.9.24</version>",
" </dependency>",
" </dependencies>",
" </dependencyManagement>",
"</project>"
));
IvyMakePom task = new IvyMakePom();
task.setIvyFile(ivyFile);
task.setPomFile(pomFile);
task.setPrintIvyInfo(false);
task.setProject(project);
task.setTemplateFile(templateFile);
IvyMakePom.Mapping mapping = task.createMapping();
mapping.setConf("default");
mapping.setScope("compile");
task.execute();
String[] expect = {
"<project>",
" <groupId>org</groupId>",
" <artifactId>name</artifactId>",
" <version>1.0.0-SNAPSHOT</version>",
" <dependencyManagement>",
" <dependencies>",
" <dependency>",
" <groupId>org.aspectj</groupId>",
" <artifactId>aspectjrt</artifactId>",
" <version>1.9.24</version>",
" </dependency>",
" </dependencies>",
" </dependencyManagement>",
" <dependencies>",
" <dependency>",
" <groupId>org.springframework</groupId>",
" <artifactId>spring-aop</artifactId>",
" <version>6.2.9</version>",
" <scope>compile</scope>",
" </dependency>",
" </dependencies>",
"</project>",
""
};
assertEquals(String.join(System.lineSeparator(), expect), readFileToString(pomFile, "UTF-8"));
}
/**
* Test case for <a href="https://issues.apache.org/jira/browse/IVY-1667">IVY-1667</a>.
*/
@Test
public void testMakePomWithTemplate1667_2() throws Exception {
File ivyFile = workdir.newFile("ivy.xml");
writeLines(ivyFile, "UTF-8", Arrays.asList(
"<ivy-module version='2.0'>",
" <info module='name' organisation='org' revision='1.0.0-SNAPSHOT' />",
" <configurations>",
" <conf name='default' />",
" </configurations>",
" <dependencies defaultconf='default' defaultconfmapping='*->master,runtime()'>",
" <dependency org='org.springframework' name='spring-core' rev='6.2.9' />",
" </dependencies>",
"</ivy-module>"
));
File pomFile = workdir.newFile("ivy.pom");
File templateFile = workdir.newFile("the.pom");
writeLines(templateFile, "UTF-8", Arrays.asList(
"<project>",
" <groupId>${ivy.pom.groupId}</groupId>",
" <artifactId>${ivy.pom.artifactId}</artifactId>",
" <version>${ivy.pom.version}</version>",
" <dependencyManagement>",
" <dependencies>",
" <dependency>",
" <groupId>org.aspectj</groupId>",
" <artifactId>aspectjrt</artifactId>",
" <version>1.9.24</version>",
" </dependency>",
" </dependencies>",
" </dependencyManagement>",
" <dependencies>",
" <dependency>",
" <groupId>org.springframework</groupId>",
" <artifactId>spring-aop</artifactId>",
" <version>6.2.9</version>",
" <scope>compile</scope>",
" </dependency>",
" </dependencies>",
"</project>"
));
IvyMakePom task = new IvyMakePom();
task.setIvyFile(ivyFile);
task.setPomFile(pomFile);
task.setPrintIvyInfo(false);
task.setProject(project);
task.setTemplateFile(templateFile);
IvyMakePom.Mapping mapping = task.createMapping();
mapping.setConf("default");
mapping.setScope("compile");
task.execute();
String[] expect = {
"<project>",
" <groupId>org</groupId>",
" <artifactId>name</artifactId>",
" <version>1.0.0-SNAPSHOT</version>",
" <dependencyManagement>",
" <dependencies>",
" <dependency>",
" <groupId>org.aspectj</groupId>",
" <artifactId>aspectjrt</artifactId>",
" <version>1.9.24</version>",
" </dependency>",
" </dependencies>",
" </dependencyManagement>",
" <dependencies>",
" <dependency>",
" <groupId>org.springframework</groupId>",
" <artifactId>spring-aop</artifactId>",
" <version>6.2.9</version>",
" <scope>compile</scope>",
" </dependency>",
" <dependency>",
" <groupId>org.springframework</groupId>",
" <artifactId>spring-core</artifactId>",
" <version>6.2.9</version>",
" <scope>compile</scope>",
" </dependency>",
" </dependencies>",
"</project>",
""
};
assertEquals(String.join(System.lineSeparator(), expect), readFileToString(pomFile, "UTF-8"));
}
//--------------------------------------------------------------------------
private static final class PomDependency { private static final class PomDependency {
private final String groupId; private final String groupId;
private final String artifactId; private final String artifactId;