Skip to content

Commit 13fcbaf

Browse files
authored
Merge pull request e-gineering#120 from glimmerveen/feature/partial-multi-module-reversioning
Extended the OtherBranchVersionExtension to deal with partial multi-module builds
2 parents 9889c7f + b30df68 commit 13fcbaf

File tree

2 files changed

+125
-2
lines changed

2 files changed

+125
-2
lines changed

src/main/java/com/e_gineering/maven/gitflowhelper/OtherBranchVersionExtension.java

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,54 @@
22

33
import com.e_gineering.maven.gitflowhelper.properties.PropertyResolver;
44
import org.apache.maven.AbstractMavenLifecycleParticipant;
5+
import org.apache.maven.Maven;
56
import org.apache.maven.MavenExecutionException;
67
import org.apache.maven.artifact.Artifact;
78
import org.apache.maven.artifact.versioning.VersionRange;
9+
import org.apache.maven.execution.DefaultMavenExecutionRequest;
10+
import org.apache.maven.execution.MavenExecutionRequest;
11+
import org.apache.maven.execution.MavenExecutionResult;
812
import org.apache.maven.execution.MavenSession;
913
import org.apache.maven.model.Dependency;
1014
import org.apache.maven.model.Model;
1115
import org.apache.maven.model.Parent;
1216
import org.apache.maven.model.Plugin;
1317
import org.apache.maven.model.ReportPlugin;
1418
import org.apache.maven.model.io.ModelWriter;
19+
import org.apache.maven.plugin.LegacySupport;
1520
import org.apache.maven.project.MavenProject;
1621
import org.codehaus.plexus.component.annotations.Component;
1722
import org.codehaus.plexus.component.annotations.Requirement;
1823

1924
import java.io.File;
2025
import java.io.IOException;
2126
import java.util.HashMap;
27+
import java.util.List;
2228
import java.util.Map;
2329

2430
@Component(role = AbstractMavenLifecycleParticipant.class, hint = "other-branch-version")
2531
public class OtherBranchVersionExtension extends AbstractBranchDetectingExtension {
2632

2733
@Requirement(role = ModelWriter.class)
2834
ModelWriter modelWriter;
35+
36+
@Requirement(role = Maven.class)
37+
Maven maven;
38+
39+
@Requirement(role = LegacySupport.class)
40+
LegacySupport legacySupport;
2941

3042
private static final int ORIGINAL_VERSION_IDX = 0;
3143
private static final int ADJUSTED_VERSION_IDX = 1;
3244

3345
@Override
3446
public void afterProjectsRead(final MavenSession session) throws MavenExecutionException {
3547
super.afterProjectsRead(session);
36-
48+
49+
if (session.getUserProperties().containsKey("gitflow.skip.extension")) {
50+
return;
51+
}
52+
3753
if (pluginFound) {
3854
logger.debug("other-branch-version extension active.");
3955
if (branchInfo != null) {
@@ -62,7 +78,60 @@ public void afterProjectsRead(final MavenSession session) throws MavenExecutionE
6278
project.getArtifact().setVersionRange(VersionRange.createFromVersion(newVersion));
6379
}
6480
}
65-
81+
82+
final MavenProject topLevelProjectInsideReactor = session.getTopLevelProject();
83+
final MavenProject topLevelProject = findTopLevelProject(topLevelProjectInsideReactor);
84+
logger.info("Top level project: " + topLevelProjectInsideReactor.getGroupId() + ":" + topLevelProjectInsideReactor.getArtifactId());
85+
if (!topLevelProjectInsideReactor.equals(topLevelProject)) {
86+
// When only the partial tree of modules is being built, not all modules could be indexed
87+
// into the cross-walk map. In order to deal with dependencies to modules outside the reactor,
88+
// Another Maven execution is performed on the 'actual' top level project. This allows the
89+
// cross-walk map to be completed with the modules that *are* part of the multi-module project,
90+
// but are currently not part of the reactor.
91+
92+
logger.info("Found top level project, but outside reactor: " + topLevelProject.getGroupId() + ":" + topLevelProject.getArtifactId() + " (" + topLevelProject.getFile() + ")");
93+
94+
// Initialization of the nested Maven execution, based on the current session's request
95+
final MavenExecutionRequest request = DefaultMavenExecutionRequest.copy(session.getRequest())
96+
.setExecutionListener(null) /* Disable the observer of the outer maven session */
97+
.setTransferListener(null) /* Disable the observer of the outer maven session */
98+
.setGoals(null) /* Disable the goals used to execute the outer maven session */
99+
.setReactorFailureBehavior(MavenExecutionRequest.REACTOR_FAIL_NEVER)
100+
.setPom(topLevelProject.getFile()) /* Use the pom file of the top-level project */
101+
.setBaseDirectory(topLevelProject.getBasedir()) /* Use the basedir of the top-level project */
102+
;
103+
// The following user property on the nested execution prevents this extension to activate
104+
// in the nested execution. This is needed, as the extension is not reentrant.
105+
request.getUserProperties().put("gitflow.skip.extension", true);
106+
107+
// Perform the nested Maven execution, and grab the list of *all* projects (ie modules of the
108+
// multi-module build).
109+
final MavenExecutionResult mavenExecutionResult;
110+
try {
111+
mavenExecutionResult = maven.execute(request);
112+
} finally {
113+
// The additional Maven execution uses a new session, and at the end of the execution
114+
// clears the Session object in LegacySupport. This may break other plugins/uses of
115+
// LegacySupport; therefore always restore the session *after* the additional Maven
116+
// execution.
117+
legacySupport.setSession(session);
118+
}
119+
final List<MavenProject> topologicallySortedProjects = mavenExecutionResult.getTopologicallySortedProjects();
120+
121+
// Iterate over these modules and process the 'new' ones just as the modules that are part
122+
// of the reactor.
123+
for (MavenProject parsedProject : topologicallySortedProjects) {
124+
if (adjustedVersions.containsKey(parsedProject)) {
125+
logger.info("Skipping " + parsedProject.getGroupId() + ":" + parsedProject.getArtifactId() + ": already part of reactor");
126+
} else {
127+
String originalVersion = PropertyResolver.resolveValue(parsedProject.getVersion(), parsedProject.getProperties(), systemEnvVars);
128+
String newVersion = getAsBranchSnapshotVersion(originalVersion, branchInfo.getName());
129+
adjustedVersions.put(parsedProject, new String[]{originalVersion, newVersion});
130+
logger.info("Updating outside-reactor project " + parsedProject.getGroupId() + ":" + parsedProject.getArtifactId() + ":" + originalVersion + " to: " + newVersion);
131+
}
132+
}
133+
}
134+
66135
// Once we have that populated, refilter the adjusted projects models
67136
// updating dependencies on both the in-memory effective model, and the original pom.xml model.
68137
for (Map.Entry<MavenProject, String[]> adjustedProject : adjustedVersions.entrySet()) {
@@ -96,6 +165,16 @@ public void afterProjectsRead(final MavenSession session) throws MavenExecutionE
96165
logger.info("Continuing execution....");
97166
}
98167

168+
private MavenProject findTopLevelProject(MavenProject mavenProject) {
169+
MavenProject parent = mavenProject;
170+
171+
while (parent.getParentFile() != null) {
172+
parent = parent.getParent();
173+
}
174+
175+
return parent;
176+
}
177+
99178
private void updateProjectModel(final MavenProject projectContext, final Model model, final String[] versions, final Map<MavenProject, String[]> adjustedVersions) {
100179
model.setVersion(versions[ADJUSTED_VERSION_IDX]);
101180

src/test/java/com/e_gineering/maven/gitflowhelper/OtherBranchIT.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,48 @@ public void attachDeployed() throws Exception {
9898
verifier.resetStreams();
9999
}
100100
}
101+
102+
@Test
103+
public void buildMultiModuleProject() throws Exception {
104+
Verifier verifier = createVerifier("/multi-module-project-stub", "origin/feature/poc/test-partial-multi-module", "5.0.0-SNAPSHOT");
105+
try {
106+
verifier.executeGoal("install");
107+
108+
// Verify that all 3 maven projects that are part of the multi-module build are recognized
109+
verifier.verifyTextInLog("Updating project com.e-gineering:gitflow-helper-maven-plugin-multi-module-parent-stub:5.0.0-SNAPSHOT to: 5.0.0+origin-feature-poc-test-partial-multi-module-SNAPSHOT");
110+
verifier.verifyTextInLog("Updating project com.e-gineering:gitflow-helper-maven-plugin-multi-module-child1-stub:5.0.0-SNAPSHOT to: 5.0.0+origin-feature-poc-test-partial-multi-module-SNAPSHOT");
111+
verifier.verifyTextInLog("Updating project com.e-gineering:gitflow-helper-maven-plugin-multi-module-child2-stub:5.0.0-SNAPSHOT to: 5.0.0+origin-feature-poc-test-partial-multi-module-SNAPSHOT");
112+
113+
verifier.verifyErrorFreeLog();
114+
} finally {
115+
verifier.resetStreams();
116+
}
117+
}
118+
119+
@Test
120+
public void partialBuildMultiModuleProject() throws Exception {
121+
// Partial builds of a multi-module project *must* be preceded by a full build
122+
buildMultiModuleProject();
123+
124+
// After a full build, try to build module child2 in isolation
125+
Verifier verifier = createVerifier("/multi-module-project-stub", "origin/feature/poc/test-partial-multi-module", "5.0.0-SNAPSHOT");
126+
try {
127+
// Only build module child2 (thus this being a partial build)
128+
verifier.addCliOption("-pl child2");
129+
verifier.executeGoal("install");
130+
131+
// Verify that the plugin detects that we are doing a partial build
132+
verifier.verifyTextInLog("Found top level project, but outside reactor: com.e-gineering:gitflow-helper-maven-plugin-multi-module-parent-stub");
133+
134+
// Verify that the dependency to a module not part of the current build *is* being rewritten
135+
verifier.verifyTextInLog("Updating outside-reactor project com.e-gineering:gitflow-helper-maven-plugin-multi-module-child1-stub:5.0.0-SNAPSHOT to: 5.0.0+origin-feature-poc-test-partial-multi-module-SNAPSHOT");
136+
137+
// Verify that the project that *is* part of the reactor is left alone in the construction of the cross-walk map.
138+
verifier.verifyTextInLog("Skipping com.e-gineering:gitflow-helper-maven-plugin-multi-module-child2-stub: already part of reactor");
139+
140+
verifier.verifyErrorFreeLog();
141+
} finally {
142+
verifier.resetStreams();
143+
}
144+
}
101145
}

0 commit comments

Comments
 (0)