You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by "Hari Krishna Dara (Jira)" <ji...@apache.org> on 2021/12/19 14:37:00 UTC
[jira] [Commented] (MNG-7368) Merge depencyManagement/dependencies instead of overwriting
[ https://issues.apache.org/jira/browse/MNG-7368?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17462191#comment-17462191 ]
Hari Krishna Dara commented on MNG-7368:
----------------------------------------
As a quick POC, I made the below change (on top of {{3.8.1}} codebase):
{code}
diff --git a/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java b/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java
index dbd548b6c..041aa7330 100644
--- a/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java
+++ b/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java
@@ -1275,8 +1275,8 @@ protected void mergeDependencyManagement( DependencyManagement target, Dependenc
protected void mergeDependencyManagement_Dependencies( DependencyManagement target, DependencyManagement source,
boolean sourceDominant, Map<Object, Object> context )
{
- target.setDependencies( merge( target.getDependencies(), source.getDependencies(),
- sourceDominant, new DependencyKeyComputer() ) );
+ target.setDependencies( merge( target.getDependencies(), source.getDependencies(), new DependencyKeyComputer(),
+ new DependencyMerger( sourceDominant ) ) );
}
protected void mergeParent( Parent target, Parent source, boolean sourceDominant, Map<Object, Object> context )
@@ -2836,6 +2836,28 @@ public T merge( T u, T v )
}
}
+ private static class DependencyMerger implements Remapping<Dependency>
+ {
+ private final boolean sourceDominant;
+
+ DependencyMerger( boolean sourceDominant )
+ {
+ this.sourceDominant = sourceDominant;
+ }
+
+ @Override
+ public Dependency merge( Dependency u, Dependency v )
+ {
+ Dependency tgt = sourceDominant ? v : u;
+ Dependency src = sourceDominant ? u : v;
+ if ( tgt.getVersion() == null && src.getVersion() != null )
+ {
+ tgt.setVersion( src.getVersion() );
+ }
+ return tgt;
+ }
+ }
+
/**
* Merge two lists
*/
{code}
and it worked for the attached sample:
{noformat}
...
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ module ---
[INFO] depman-inheritance:module:jar:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.11:compile
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:compile
[INFO] \- org.apache.commons:commons-text:jar:1.9:compile
[INFO] \- org.apache.commons:commons-lang3:jar:3.11:compile
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for project 1.0-SNAPSHOT:
[INFO]
[INFO] project ............................................ SUCCESS [ 0.557 s]
[INFO] module1 ............................................ SUCCESS [ 0.055 s]
...
{noformat}
> Merge depencyManagement/dependencies instead of overwriting
> -----------------------------------------------------------
>
> Key: MNG-7368
> URL: https://issues.apache.org/jira/browse/MNG-7368
> Project: Maven
> Issue Type: Improvement
> Components: Inheritance and Interpolation
> Affects Versions: 3.8.1
> Reporter: Hari Krishna Dara
> Priority: Major
> Labels: dependencies, dependency
> Attachments: depman-inheritance-1.zip
>
>
> When inheriting {{dependencyManagement}} from parent, Maven's current merge logic is at the level of the list of {{dependencies}} which involves choosing the entire child's {{dependency}} definition over that of the parent, i.e., no merging actually happens at the {{dependency}} level (it is all or nothing). This essentially makes it impossible to incrementally build the {{dependencyManagement}}. If the child projects have to repeat the entire {{dependency}} definition, it defeats the purpose of sharing them in a parent-pom across multiple related projects. E.g., one common reason for managing them in parent is to centralize {{version}} for all dependencies at one place, but if the child must repeat the {{version}} to change anything in that dependency such as {{scope}} or {{exclusion}} rules, then there is no longer one central place.
> I am attaching a very basic project structure (also attached as {{depman-inheritance.zip}}) to better demonstrate the issue.
> Parent POM with a couple of dependencies:
> {code:xml|title=parent/pom.xml}
> <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>depman-inheritance</groupId>
> <artifactId>parent</artifactId>
> <version>1.0-SNAPSHOT</version>
> <name>parent</name>
> <packaging>pom</packaging>
> <dependencyManagement>
> <dependencies>
> <dependency>
> <groupId>junit</groupId>
> <artifactId>junit</artifactId>
> <version>4.11</version>
> <scope>test</scope>
> </dependency>
> <dependency>
> <groupId>org.apache.commons</groupId>
> <artifactId>commons-text</artifactId>
> <version>1.9</version>
> </dependency>
> </dependencies>
> </dependencyManagement>
> </project>
> {code}
> Project Root POM trying to change just the scope of one of the dependencies:
> {code:xml|title=project/pom.xml}
> <?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>
> <parent>
> <groupId>depman-inheritance</groupId>
> <artifactId>parent</artifactId>
> <version>1.0-SNAPSHOT</version>
> <relativePath>../parent/pom.xml</relativePath>
> </parent>
> <groupId>depman-inheritance</groupId>
> <artifactId>project</artifactId>
> <version>1.0-SNAPSHOT</version>
> <name>project</name>
> <packaging>pom</packaging>
> <modules>
> <module>module</module>
> </modules>
> <dependencyManagement>
> <dependencies>
> <dependency>
> <groupId>junit</groupId>
> <artifactId>junit</artifactId>
> <scope>compile</scope>
> </dependency>
> </dependencies>
> </dependencyManagement>
> </project>
> {code}
> Module POM simply using the dependencies:
> {code:xml|title=project/module/pom.xml}
> <?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>
> <parent>
> <groupId>depman-inheritance</groupId>
> <artifactId>project</artifactId>
> <version>1.0-SNAPSHOT</version>
> </parent>
> <groupId>depman-inheritance</groupId>
> <artifactId>module</artifactId>
> <version>1.0-SNAPSHOT</version>
> <name>module1</name>
> <dependencies>
> <dependency>
> <groupId>junit</groupId>
> <artifactId>junit</artifactId>
> </dependency>
> <dependency>
> <groupId>org.apache.commons</groupId>
> <artifactId>commons-text</artifactId>
> </dependency>
> </dependencies>
> </project>
> {code}
> With this, if we run any maven command in the project, I get the below error:
> {code}
> $ mvn dependency:tree
> ...
> [ERROR] [ERROR] Some problems were encountered while processing the POMs:
> [ERROR] 'dependencies.dependency.version' for junit:junit:jar is missing. @ line 17, column 17
> @
> [ERROR] The build could not read 1 project -> [Help 1]
> [ERROR]
> [ERROR] The project depman-inheritance:module:1.0-SNAPSHOT (/Users/hdara/git/hdara/playground-mvn-project/depman-inheritance/project/module/pom.xml) has 1 error
> [ERROR] 'dependencies.dependency.version' for junit:junit:jar is missing. @ line 17, column 17
> ...
> {code}
> I would like to propose that the support for deeper merging be added to Maven. There are however two aspects of this merging that I am not sure:
> - Should/Can it be applied to all non-key fields?
> - How to handle exclusion rules? Should they be overriding or be additive?
--
This message was sent by Atlassian Jira
(v8.20.1#820001)