Merge pull request #114 from eric-milles/IVY-1653

IVY-1653: `makepom`: write overrides to Maven `dependencyManagement` section
This commit is contained in:
Maarten Coene 2026-06-17 20:12:07 +02:00 committed by GitHub
commit c33191f88d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 230 additions and 9 deletions

View File

@ -21,5 +21,5 @@
under the License.
-->
<suppressions>
<suppress checks="MagicNumber" files=".*[\\/]test[\\/]java[\\/].*"/>
<suppress checks="MagicNumber" files="[\\/]test[\\/]java[\\/]|PomModuleDescriptorWriter\.java$"/>
</suppressions>

View File

@ -38,11 +38,15 @@ import org.apache.ivy.core.IvyPatternHelper;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.DependencyArtifactDescriptor;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.descriptor.DependencyDescriptorMediator;
import org.apache.ivy.core.module.descriptor.ExcludeRule;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.descriptor.OverrideDependencyDescriptorMediator;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.core.module.id.ModuleRules;
import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.core.settings.IvyVariableContainer;
import org.apache.ivy.plugins.matcher.MapMatcher;
import org.apache.ivy.plugins.parser.m2.PomWriterOptions.ConfigurationScopeMapping;
import org.apache.ivy.plugins.parser.m2.PomWriterOptions.ExtraDependency;
import org.apache.ivy.util.ConfigurationUtils;
@ -112,6 +116,7 @@ public final class PomModuleDescriptorWriter {
boolean dependencyManagement = false;
boolean dependenciesPrinted = false;
boolean overridesPrinted = false;
int lastIndent = 0;
int indent = 0;
@ -135,14 +140,26 @@ public final class PomModuleDescriptorWriter {
dependencyManagement = false;
}
if (line.contains("</dependencies>") && !dependenciesPrinted && !dependencyManagement) {
printDependencies(md, out, options, indent, false);
dependenciesPrinted = true;
if (line.contains("</dependencies>")) {
if (!overridesPrinted && dependencyManagement) {
printOverrides(md, out, indent, false);
overridesPrinted = true;
}
if (!dependenciesPrinted && !dependencyManagement) {
printDependencies(md, out, options, indent, false);
dependenciesPrinted = true;
}
}
if (line.contains("</project>") && !dependenciesPrinted) {
printDependencies(md, out, options, lastIndent, true);
dependenciesPrinted = true;
if (line.contains("</project>")) {
if (!overridesPrinted) {
printOverrides(md, out, lastIndent, true);
overridesPrinted = true;
}
if (!dependenciesPrinted) {
printDependencies(md, out, options, lastIndent, true);
dependenciesPrinted = true;
}
}
}
out.println(line);
@ -342,8 +359,59 @@ public final class PomModuleDescriptorWriter {
out.println("</exclusions>");
}
private static DependencyDescriptor[] getDependencies(ModuleDescriptor md,
PomWriterOptions options) {
private static void printOverrides(ModuleDescriptor md, PrintWriter out, int indent, boolean container) {
ModuleRules<DependencyDescriptorMediator> mr = md.getAllDependencyDescriptorMediators();
Map<MapMatcher, DependencyDescriptorMediator> m = new LinkedHashMap<>(mr.getAllRules());
m.values().removeIf(value -> !(value instanceof OverrideDependencyDescriptorMediator));
m.keySet().removeIf(key -> {
String artifactId = key.getAttributes().get("module");
return artifactId == null || artifactId.equals("*");
});
m.keySet().removeIf(key -> {
String groupId = key.getAttributes().get("organisation");
return groupId == null || groupId.equals("*");
});
if (m.isEmpty()) {
return;
}
if (container) {
indent(out, indent);
out.println("<dependencyManagement>");
indent(out, indent * 2);
out.println("<dependencies>");
} else {
indent /= 2; // <dependencies> is second-level child of <project>
}
for (Map.Entry<MapMatcher, DependencyDescriptorMediator> entry : m.entrySet()) {
String artifactId = entry.getKey().getAttributes().get("module");
String groupId = entry.getKey().getAttributes().get("organisation");
String version = ((OverrideDependencyDescriptorMediator) entry.getValue()).getVersion();
indent(out, indent * 3);
out.println("<dependency>");
indent(out, indent * 4);
out.println("<groupId>" + groupId + "</groupId>");
indent(out, indent * 4);
out.println("<artifactId>" + artifactId + "</artifactId>");
indent(out, indent * 4);
out.println("<version>" + version + "</version>");
indent(out, indent * 3);
out.println("</dependency>");
}
if (container) {
indent(out, indent * 2);
out.println("</dependencies>");
indent(out, indent);
out.println("</dependencyManagement>");
}
}
private static DependencyDescriptor[] getDependencies(ModuleDescriptor md, PomWriterOptions options) {
String[] confs = ConfigurationUtils.replaceWildcards(options.getConfs(), md);
List<DependencyDescriptor> result = new ArrayList<>();

View File

@ -100,6 +100,73 @@ public class IvyMakePomTest {
assertTrue("Some expected dependencies " + expectedPomArtifactIds + " were not found in the generated POM file", expectedPomArtifactIds.isEmpty());
}
/**
* Test case for <a href="https://issues.apache.org/jira/browse/IVY-1653">IVY-1653</a>.
*/
@Test
public void testMakePom1653() throws Exception {
File ivyFile = workdir.newFile("ivy-1653.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' />",
" <override org='org.aspectj' module='aspectjrt' rev='1.9.24' />",
" </dependencies>",
"</ivy-module>"
));
File pomFile = workdir.newFile("ivy-1653.pom");
IvyMakePom task = new IvyMakePom();
task.setIvyFile(ivyFile);
task.setPomFile(pomFile);
task.setPrintIvyInfo(false);
task.setProject(project);
IvyMakePom.Mapping mapping = task.createMapping();
mapping.setConf("default");
mapping.setScope("compile");
task.execute();
String[] expect = {
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">",
"",
" <modelVersion>4.0.0</modelVersion>",
" <groupId>org</groupId>",
" <artifactId>name</artifactId>",
" <packaging>jar</packaging>",
" <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
public void testMakePomWithTemplate() throws Exception {
File ivyFile = workdir.newFile("ivy.xml");
@ -173,6 +240,92 @@ public class IvyMakePomTest {
assertEquals(String.join(System.lineSeparator(), expect), readFileToString(pomFile, "UTF-8"));
}
/**
* Test case for <a href="https://issues.apache.org/jira/browse/IVY-1653">IVY-1653</a>.
*/
@Test
public void testMakePomWithTemplate1653() 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' />",
" <override org='org.springframework' module='spring-core' rev='6.2.19' />",
" </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>",
" <dependency>",
" <groupId>org.springframework</groupId>",
" <artifactId>spring-core</artifactId>",
" <version>6.2.19</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>.
*/