Skip to content

Commit c828e76

Browse files
committed
feat: Initial commit
0 parents  commit c828e76

File tree

3 files changed

+198
-0
lines changed

3 files changed

+198
-0
lines changed

.gitignore

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
target/
2+
!.mvn/wrapper/maven-wrapper.jar
3+
!**/src/main/**/target/
4+
!**/src/test/**/target/
5+
6+
### IntelliJ IDEA ###
7+
.idea/modules.xml
8+
.idea/jarRepositories.xml
9+
.idea/compiler.xml
10+
.idea/libraries/
11+
*.iws
12+
*.iml
13+
*.ipr
14+
.idea
15+
16+
### Eclipse ###
17+
.apt_generated
18+
.classpath
19+
.factorypath
20+
.project
21+
.settings
22+
.springBeans
23+
.sts4-cache
24+
25+
### NetBeans ###
26+
/nbproject/private/
27+
/nbbuild/
28+
/dist/
29+
/nbdist/
30+
/.nb-gradle/
31+
build/
32+
!**/src/main/**/build/
33+
!**/src/test/**/build/
34+
35+
### VS Code ###
36+
.vscode/
37+
38+
### Mac OS ###
39+
.DS_Store

pom.xml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>de.rub.nds</groupId>
8+
<artifactId>relaxed-dependency-convergence-rule</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<name>Relaxed Dependency Convergence Rule</name>
12+
<description>A custom maven enforcer rule that works similar to dependencyConvergence but is limited to contradicting major versions</description>
13+
14+
<properties>
15+
<api.version>3.5.0</api.version>
16+
<mavenVersion>3.6.3</mavenVersion>
17+
<maven.compiler.source>11</maven.compiler.source>
18+
<maven.compiler.target>11</maven.compiler.target>
19+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
20+
</properties>
21+
22+
<dependencies>
23+
<dependency>
24+
<groupId>org.apache.maven.enforcer</groupId>
25+
<artifactId>enforcer-api</artifactId>
26+
<version>${api.version}</version>
27+
<scope>provided</scope>
28+
</dependency>
29+
<dependency>
30+
<groupId>org.apache.maven</groupId>
31+
<artifactId>maven-core</artifactId>
32+
<version>${mavenVersion}</version>
33+
<scope>provided</scope>
34+
</dependency>
35+
<dependency>
36+
<groupId>javax.inject</groupId>
37+
<artifactId>javax.inject</artifactId>
38+
<version>1</version>
39+
<scope>provided</scope>
40+
</dependency>
41+
<dependency>
42+
<groupId>org.apache.maven.shared</groupId>
43+
<artifactId>maven-dependency-tree</artifactId>
44+
<version>3.3.0</version>
45+
</dependency>
46+
</dependencies>
47+
48+
<build>
49+
<plugins>
50+
<plugin>
51+
<!-- generate index of project components -->
52+
<groupId>org.eclipse.sisu</groupId>
53+
<artifactId>sisu-maven-plugin</artifactId>
54+
<version>0.9.0.M1</version>
55+
<executions>
56+
<execution>
57+
<goals>
58+
<goal>main-index</goal>
59+
</goals>
60+
</execution>
61+
</executions>
62+
</plugin>
63+
</plugins>
64+
</build>
65+
</project>
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package de.rub.nds.enforcer.rules.dependency;
2+
3+
import org.apache.maven.artifact.Artifact;
4+
import org.apache.maven.enforcer.rule.api.AbstractEnforcerRule;
5+
import org.apache.maven.enforcer.rule.api.EnforcerRuleError;
6+
import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
7+
import org.apache.maven.execution.MavenSession;
8+
import org.apache.maven.project.DefaultProjectBuildingRequest;
9+
import org.apache.maven.project.MavenProject;
10+
import org.apache.maven.project.ProjectBuildingRequest;
11+
import org.apache.maven.rtinfo.RuntimeInformation;
12+
import org.apache.maven.shared.dependency.graph.*;
13+
import org.apache.maven.shared.dependency.graph.traversal.CollectingDependencyNodeVisitor;
14+
15+
import javax.inject.Inject;
16+
import javax.inject.Named;
17+
import java.util.*;
18+
19+
@Named("relaxedDependencyConvergence")
20+
public class RelaxedDependencyConvergenceRule extends AbstractEnforcerRule {
21+
22+
@Inject
23+
private MavenProject project;
24+
25+
@Inject
26+
private MavenSession session;
27+
28+
@Inject
29+
private DependencyCollectorBuilder dependencyCollectorBuilder;
30+
31+
@Override
32+
public void execute() throws EnforcerRuleException {
33+
// Collect major versions of all dependencies
34+
Map<String, Set<String>> majorVersions = new HashMap<>();
35+
36+
ProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());
37+
buildingRequest.setProject(project);
38+
try {
39+
DependencyNode rootNode = dependencyCollectorBuilder.collectDependencyGraph(buildingRequest, null);
40+
collectMajorVersions(rootNode, majorVersions);
41+
} catch (DependencyCollectorBuilderException e) {
42+
throw new EnforcerRuleError(e);
43+
}
44+
45+
// Check for major version conflicts (i.e., set size > 1)
46+
List<String> conflicts = new ArrayList<>();
47+
for (Map.Entry<String, Set<String>> entry : majorVersions.entrySet()) {
48+
if (entry.getValue().size() > 1) {
49+
conflicts.add(entry.getKey() + " -> major versions: " + entry.getValue());
50+
}
51+
}
52+
53+
// Throw if at least one major version conflict has been detected
54+
if (!conflicts.isEmpty()) {
55+
throw new EnforcerRuleException("Major version conflicts detected:\n" + String.join("\n", conflicts));
56+
}
57+
}
58+
59+
private void collectMajorVersions(DependencyNode rootNode, Map<String, Set<String>> versions) {
60+
CollectingDependencyNodeVisitor visitor = new CollectingDependencyNodeVisitor();
61+
rootNode.accept(visitor);
62+
for (DependencyNode node : visitor.getNodes()) {
63+
Artifact artifact = node.getArtifact();
64+
if (artifact == null) {
65+
continue;
66+
}
67+
String key = artifact.getGroupId() + ":" + artifact.getArtifactId();
68+
String major;
69+
if (node.getPremanagedVersion() != null && !isVersionRange(node.getPremanagedVersion())) {
70+
major = extractMajorVersion(node.getPremanagedVersion());
71+
} else {
72+
major = extractMajorVersion(artifact.getVersion());
73+
}
74+
if (major != null) {
75+
versions.computeIfAbsent(key, k -> new HashSet<>()).add(major);
76+
}
77+
}
78+
}
79+
80+
private String extractMajorVersion(String version) {
81+
String baseVersion = version.split("-")[0];
82+
String[] parts = baseVersion.split("\\.");
83+
return parts.length > 0 ? parts[0] : version;
84+
}
85+
86+
private boolean isVersionRange(String version) {
87+
return version.contains("[") || version.contains("]") || version.contains("(") || version.contains(")");
88+
}
89+
90+
@Override
91+
public String toString() {
92+
return "RelaxedDependencyConvergenceRule{}";
93+
}
94+
}

0 commit comments

Comments
 (0)