You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by rf...@apache.org on 2020/04/20 18:42:25 UTC
[maven] 01/06: Support --also-make flag in combination with
--resume-from.
This is an automated email from the ASF dual-hosted git repository.
rfscholte pushed a commit to branch MNG-6863
in repository https://gitbox.apache.org/repos/asf/maven.git
commit 56a163aa495c9e459811727bd43ac511e2c6c992
Author: Martin Kanters <Ma...@infosupport.com>
AuthorDate: Wed Apr 8 21:25:52 2020 +0200
Support --also-make flag in combination with --resume-from.
Calculate up and downstream dependencies after filtering projects for the --resume-from flag.
---
.../apache/maven/graph/DefaultGraphBuilder.java | 135 ++++++++-------
.../maven/graph/DefaultGraphBuilderTest.java | 187 +++++++++++++++++++++
2 files changed, 264 insertions(+), 58 deletions(-)
diff --git a/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java b/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java
index 6d15230..07a4cf0 100644
--- a/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java
+++ b/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java
@@ -125,8 +125,8 @@ public class DefaultGraphBuilder
ProjectDependencyGraph projectDependencyGraph = new DefaultProjectDependencyGraph( projects );
List<MavenProject> activeProjects = projectDependencyGraph.getSortedProjects();
activeProjects = trimSelectedProjects( activeProjects, projectDependencyGraph, session.getRequest() );
+ activeProjects = trimResumedProjects( activeProjects, projectDependencyGraph, session.getRequest() );
activeProjects = trimExcludedProjects( activeProjects, session.getRequest() );
- activeProjects = trimResumedProjects( activeProjects, session.getRequest() );
if ( activeProjects.size() != projectDependencyGraph.getSortedProjects().size() )
{
@@ -144,6 +144,8 @@ public class DefaultGraphBuilder
if ( !request.getSelectedProjects().isEmpty() )
{
+ result = new ArrayList<>( projects.size() );
+
File reactorDirectory = null;
if ( request.getBaseDirectory() != null )
{
@@ -176,52 +178,54 @@ public class DefaultGraphBuilder
}
}
- boolean makeUpstream = false;
- boolean makeDownstream = false;
+ result.addAll( selectedProjects );
- if ( MavenExecutionRequest.REACTOR_MAKE_UPSTREAM.equals( request.getMakeBehavior() ) )
- {
- makeUpstream = true;
- }
- else if ( MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM.equals( request.getMakeBehavior() ) )
- {
- makeDownstream = true;
- }
- else if ( MavenExecutionRequest.REACTOR_MAKE_BOTH.equals( request.getMakeBehavior() ) )
- {
- makeUpstream = true;
- makeDownstream = true;
- }
- else if ( StringUtils.isNotEmpty( request.getMakeBehavior() ) )
- {
- throw new MavenExecutionException( "Invalid reactor make behavior: " + request.getMakeBehavior(),
- request.getPom() );
- }
+ result = includeAlsoMakeTransitives( result, request, graph );
+ }
+
+ return result;
+ }
+
+ private List<MavenProject> trimResumedProjects( List<MavenProject> projects, ProjectDependencyGraph graph,
+ MavenExecutionRequest request )
+ throws MavenExecutionException
+ {
+ List<MavenProject> result = projects;
- if ( makeUpstream || makeDownstream )
+ if ( StringUtils.isNotEmpty( request.getResumeFrom() ) )
+ {
+ File reactorDirectory = null;
+ if ( request.getBaseDirectory() != null )
{
- for ( MavenProject selectedProject : new ArrayList<>( selectedProjects ) )
- {
- if ( makeUpstream )
- {
- selectedProjects.addAll( graph.getUpstreamProjects( selectedProject, true ) );
- }
- if ( makeDownstream )
- {
- selectedProjects.addAll( graph.getDownstreamProjects( selectedProject, true ) );
- }
- }
+ reactorDirectory = new File( request.getBaseDirectory() );
}
- result = new ArrayList<>( selectedProjects.size() );
+ String selector = request.getResumeFrom();
+
+ result = new ArrayList<>( projects.size() );
+
+ boolean resumed = false;
for ( MavenProject project : projects )
{
- if ( selectedProjects.contains( project ) )
+ if ( !resumed && isMatchingProject( project, selector, reactorDirectory ) )
+ {
+ resumed = true;
+ }
+
+ if ( resumed )
{
result.add( project );
}
}
+
+ if ( !resumed )
+ {
+ throw new MavenExecutionException( "Could not find project to resume reactor build from: " + selector
+ + " vs " + formatProjects( projects ), request.getPom() );
+ }
+
+ result = includeAlsoMakeTransitives( result, request, graph );
}
return result;
@@ -280,42 +284,57 @@ public class DefaultGraphBuilder
return result;
}
- private List<MavenProject> trimResumedProjects( List<MavenProject> projects, MavenExecutionRequest request )
- throws MavenExecutionException
+ private List<MavenProject> includeAlsoMakeTransitives( List<MavenProject> projects, MavenExecutionRequest request,
+ ProjectDependencyGraph graph )
+ throws MavenExecutionException
{
- List<MavenProject> result = projects;
-
- if ( StringUtils.isNotEmpty( request.getResumeFrom() ) )
- {
- File reactorDirectory = null;
- if ( request.getBaseDirectory() != null )
- {
- reactorDirectory = new File( request.getBaseDirectory() );
- }
+ List<MavenProject> result;
- String selector = request.getResumeFrom();
+ boolean makeUpstream = false;
+ boolean makeDownstream = false;
- result = new ArrayList<>( projects.size() );
+ if ( MavenExecutionRequest.REACTOR_MAKE_UPSTREAM.equals( request.getMakeBehavior() ) )
+ {
+ makeUpstream = true;
+ }
+ else if ( MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM.equals( request.getMakeBehavior() ) )
+ {
+ makeDownstream = true;
+ }
+ else if ( MavenExecutionRequest.REACTOR_MAKE_BOTH.equals( request.getMakeBehavior() ) )
+ {
+ makeUpstream = true;
+ makeDownstream = true;
+ }
+ else if ( StringUtils.isNotEmpty( request.getMakeBehavior() ) )
+ {
+ throw new MavenExecutionException( "Invalid reactor make behavior: " + request.getMakeBehavior(),
+ request.getPom() );
+ }
- boolean resumed = false;
+ if ( makeUpstream || makeDownstream )
+ {
- for ( MavenProject project : projects )
+ for ( MavenProject project : new ArrayList<>( projects ) )
{
- if ( !resumed && isMatchingProject( project, selector, reactorDirectory ) )
+ if ( makeUpstream )
{
- resumed = true;
+ projects.addAll( graph.getUpstreamProjects( project, true ) );
}
-
- if ( resumed )
+ if ( makeDownstream )
{
- result.add( project );
+ projects.addAll( graph.getDownstreamProjects( project, true ) );
}
}
+ }
- if ( !resumed )
+ result = new ArrayList<>( projects.size() );
+
+ for ( MavenProject project : graph.getSortedProjects() )
+ {
+ if ( projects.contains( project ) )
{
- throw new MavenExecutionException( "Could not find project to resume reactor build from: " + selector
- + " vs " + formatProjects( projects ), request.getPom() );
+ result.add( project );
}
}
diff --git a/maven-core/src/test/java/org/apache/maven/graph/DefaultGraphBuilderTest.java b/maven-core/src/test/java/org/apache/maven/graph/DefaultGraphBuilderTest.java
new file mode 100644
index 0000000..93db7c1
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/graph/DefaultGraphBuilderTest.java
@@ -0,0 +1,187 @@
+package org.apache.maven.graph;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.execution.ProjectDependencyGraph;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.building.Result;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.ProjectBuilder;
+import org.apache.maven.project.ProjectBuildingRequest;
+import org.apache.maven.project.ProjectBuildingResult;
+import org.codehaus.plexus.util.StringUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static junit.framework.TestCase.assertEquals;
+import static org.apache.maven.execution.MavenExecutionRequest.*;
+import static org.apache.maven.execution.MavenExecutionRequest.REACTOR_MAKE_UPSTREAM;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith( Parameterized.class )
+public class DefaultGraphBuilderTest
+{
+ private static final String MODULE_A = "module-a";
+ private static final String MODULE_B = "module-b";
+ private static final String MODULE_C = "module-c";
+
+ @InjectMocks
+ private DefaultGraphBuilder graphBuilder;
+
+ @Mock
+ private ProjectBuilder projectBuilder;
+
+ @Mock
+ private MavenSession session;
+
+ @Mock
+ private MavenExecutionRequest mavenExecutionRequest;
+
+ private Map<String, MavenProject> artifactIdProjectMap;
+
+ // Parameters for the test
+ private String parameterDescription;
+ private List<String> parameterSelectedProjects;
+ private List<String> parameterExcludedProjects;
+ private String parameterResumeFrom;
+ private String parameterMakeBehavior;
+ private List<String> parameterExpectedReactorProjects;
+
+ @Parameters
+ public static Collection<Object[]> parameters()
+ {
+ return asList( new Object[][] {
+ { "Full reactor", emptyList(), emptyList(), "", "", asList( MODULE_A, MODULE_B, MODULE_C ) },
+ { "Selected project", singletonList( MODULE_B ), emptyList(), "", "", singletonList( MODULE_B )},
+ { "Excluded project", emptyList(), singletonList( MODULE_B ), "", "", asList( MODULE_A, MODULE_C )},
+ { "Resuming from project", emptyList(), emptyList(), MODULE_B, "", asList( MODULE_B, MODULE_C )},
+ { "Selected project with also make dependencies", singletonList( MODULE_C ), emptyList(), "", REACTOR_MAKE_UPSTREAM, asList( MODULE_B, MODULE_C )},
+ { "Selected project with also make dependents", singletonList( MODULE_B ), emptyList(), "", REACTOR_MAKE_DOWNSTREAM, asList( MODULE_B, MODULE_C )},
+ { "Resuming from project with also make dependencies", emptyList(), emptyList(), MODULE_C, REACTOR_MAKE_UPSTREAM, asList( MODULE_B, MODULE_C )},
+ { "Selected project with resume from an also make dependency (MNG-4960 IT#1)", singletonList( MODULE_C ), emptyList(), MODULE_B, REACTOR_MAKE_UPSTREAM, asList( MODULE_B, MODULE_C )},
+ { "Selected project with resume from an also make dependent (MNG-4960 IT#2)", singletonList( MODULE_B ), emptyList(), MODULE_C, REACTOR_MAKE_DOWNSTREAM, singletonList( MODULE_C )}
+ } );
+ }
+
+ public DefaultGraphBuilderTest( String description, List<String> selectedProjects, List<String> excludedProjects, String resumedFrom, String makeBehavior, List<String> expectedReactorProjects )
+ {
+ this.parameterDescription = description;
+ this.parameterSelectedProjects = selectedProjects;
+ this.parameterExcludedProjects = excludedProjects;
+ this.parameterResumeFrom = resumedFrom;
+ this.parameterMakeBehavior = makeBehavior;
+ this.parameterExpectedReactorProjects = expectedReactorProjects;
+ }
+
+ @Test
+ public void test()
+ {
+ // Given
+ List<String> selectedProjects = parameterSelectedProjects.stream().map( p -> ":" + p ).collect( Collectors.toList() );
+ List<String> excludedProjects = parameterExcludedProjects.stream().map( p -> ":" + p ).collect( Collectors.toList() );
+
+ when( mavenExecutionRequest.getSelectedProjects() ).thenReturn( selectedProjects );
+ when( mavenExecutionRequest.getExcludedProjects() ).thenReturn( excludedProjects );
+ when( mavenExecutionRequest.getMakeBehavior() ).thenReturn( parameterMakeBehavior );
+ if ( StringUtils.isNotEmpty( parameterResumeFrom ) )
+ {
+ when( mavenExecutionRequest.getResumeFrom() ).thenReturn( ":" + parameterResumeFrom );
+ }
+
+ // When
+ Result<ProjectDependencyGraph> result = graphBuilder.build( session );
+
+ // Then
+ List<MavenProject> actualReactorProjects = result.get().getSortedProjects();
+ List<MavenProject> expectedReactorProjects = parameterExpectedReactorProjects.stream()
+ .map( artifactIdProjectMap::get )
+ .collect( Collectors.toList());
+ assertEquals( parameterDescription, expectedReactorProjects, actualReactorProjects );
+ }
+
+ @Before
+ public void before() throws Exception
+ {
+ MockitoAnnotations.initMocks( this );
+
+ ProjectBuildingRequest projectBuildingRequest = mock( ProjectBuildingRequest.class );
+ ProjectBuildingResult projectBuildingResult1 = mock( ProjectBuildingResult.class );
+ ProjectBuildingResult projectBuildingResult2 = mock( ProjectBuildingResult.class );
+ ProjectBuildingResult projectBuildingResult3 = mock( ProjectBuildingResult.class );
+ MavenProject projectModuleA = getMockMavenProject( "module-a" );
+ MavenProject projectModuleB = getMockMavenProject( "module-b" );
+ MavenProject projectModuleC = getMockMavenProject( "module-c" );
+ Dependency dependencyOnModuleB = mock( Dependency.class );
+
+ when( session.getRequest() ).thenReturn( mavenExecutionRequest );
+ when( session.getProjects() ).thenReturn( null ); // needed, otherwise it will be an empty list by default
+
+ when( mavenExecutionRequest.getProjectBuildingRequest() ).thenReturn( projectBuildingRequest );
+ when( mavenExecutionRequest.getPom() ).thenReturn( new File( "/tmp/unit-test" ) );
+
+ when( projectBuildingResult1.getProject() ).thenReturn( projectModuleA );
+ when( projectBuildingResult2.getProject() ).thenReturn( projectModuleB );
+ when( projectBuildingResult3.getProject() ).thenReturn( projectModuleC );
+
+ when( projectBuilder.build( anyList(), anyBoolean(), any( ProjectBuildingRequest.class ) ) ).thenReturn( asList( projectBuildingResult1, projectBuildingResult2, projectBuildingResult3 ) );
+
+ when( dependencyOnModuleB.getGroupId() ).thenReturn( "org.apache.maven.graph.unittest" );
+ when( dependencyOnModuleB.getArtifactId() ).thenReturn( "module-b" );
+ when( dependencyOnModuleB.getVersion() ).thenReturn( "1.0" );
+ when( projectModuleC.getDependencies() ).thenReturn( singletonList( dependencyOnModuleB ) );
+
+ artifactIdProjectMap = ImmutableMap.of(
+ MODULE_A, projectModuleA,
+ MODULE_B, projectModuleB,
+ MODULE_C, projectModuleC
+ );
+ }
+
+ private MavenProject getMockMavenProject( String artifactId )
+ {
+ MavenProject mavenProject = mock( MavenProject.class );
+ when( mavenProject.getGroupId() ).thenReturn( "org.apache.maven.graph.unittest" );
+ when( mavenProject.getArtifactId() ).thenReturn( artifactId );
+ when( mavenProject.getVersion() ).thenReturn( "1.0" );
+ when( mavenProject.getModel() ).thenReturn( mock( Model.class ) );
+ return mavenProject;
+ }
+}
\ No newline at end of file