mirror of https://github.com/apache/maven.git
o Restored reactor failure behaviors
git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@792111 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
88062f08dd
commit
52519425f7
|
@ -146,6 +146,8 @@ public class DefaultMaven
|
|||
projects = projectSorter.getSortedProjects();
|
||||
|
||||
session.setProjects( projects );
|
||||
|
||||
session.setProjectDependencyGraph( new DefaultProjectDependencyGraph( projectSorter ) );
|
||||
}
|
||||
catch ( CycleDetectedException e )
|
||||
{
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
package org.apache.maven;
|
||||
|
||||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.execution.ProjectDependencyGraph;
|
||||
import org.apache.maven.execution.ProjectSorter;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
|
||||
/**
|
||||
* Describes the inter-dependencies between projects in the reactor.
|
||||
*
|
||||
* @author Benjamin Bentmann
|
||||
*/
|
||||
class DefaultProjectDependencyGraph
|
||||
implements ProjectDependencyGraph
|
||||
{
|
||||
|
||||
private ProjectSorter sorter;
|
||||
|
||||
/**
|
||||
* Creates a new project dependency graph based on the specified project sorting.
|
||||
*
|
||||
* @param sorter The project sorter backing the graph, must not be {@code null}.
|
||||
*/
|
||||
public DefaultProjectDependencyGraph( ProjectSorter sorter )
|
||||
{
|
||||
if ( sorter == null )
|
||||
{
|
||||
throw new IllegalArgumentException( "project sorter missing" );
|
||||
}
|
||||
|
||||
this.sorter = sorter;
|
||||
}
|
||||
|
||||
public List<MavenProject> getSortedProjects()
|
||||
{
|
||||
return new ArrayList<MavenProject>( sorter.getSortedProjects() );
|
||||
}
|
||||
|
||||
public List<MavenProject> getDownstreamProjects( MavenProject project, boolean transitive )
|
||||
{
|
||||
if ( project == null )
|
||||
{
|
||||
throw new IllegalArgumentException( "project missing" );
|
||||
}
|
||||
|
||||
Collection<String> projectIds = new HashSet<String>();
|
||||
|
||||
getDownstreamProjects( ProjectSorter.getId( project ), projectIds, transitive );
|
||||
|
||||
List<MavenProject> projects = new ArrayList<MavenProject>();
|
||||
|
||||
for ( MavenProject p : sorter.getSortedProjects() )
|
||||
{
|
||||
if ( projectIds.contains( ProjectSorter.getId( p ) ) )
|
||||
{
|
||||
projects.add( p );
|
||||
}
|
||||
}
|
||||
|
||||
return projects;
|
||||
}
|
||||
|
||||
private void getDownstreamProjects( String projectId, Collection<String> projectIds, boolean transitive )
|
||||
{
|
||||
for ( String id : sorter.getDependents( projectId ) )
|
||||
{
|
||||
projectIds.add( id );
|
||||
|
||||
if ( transitive )
|
||||
{
|
||||
getDownstreamProjects( id, projectIds, transitive );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return sorter.getSortedProjects().toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -20,7 +20,9 @@ package org.apache.maven.execution;
|
|||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
@ -53,7 +55,11 @@ public class MavenSession
|
|||
private List<MavenProject> projects;
|
||||
|
||||
private MavenProject topLevelProject;
|
||||
|
||||
|
||||
private ProjectDependencyGraph projectDependencyGraph;
|
||||
|
||||
private Collection<String> blackListedProjects;
|
||||
|
||||
@Deprecated
|
||||
public MavenSession( PlexusContainer container, MavenExecutionRequest request, MavenExecutionResult result, MavenProject project )
|
||||
{
|
||||
|
@ -198,4 +204,40 @@ public class MavenSession
|
|||
return pluginContext;
|
||||
}
|
||||
|
||||
public void setProjectDependencyGraph( ProjectDependencyGraph projectDependencyGraph )
|
||||
{
|
||||
this.projectDependencyGraph = projectDependencyGraph;
|
||||
}
|
||||
|
||||
public String getReactorFailureBehavior()
|
||||
{
|
||||
return request.getReactorFailureBehavior();
|
||||
}
|
||||
|
||||
public boolean isBlackListed( MavenProject project )
|
||||
{
|
||||
return blackListedProjects != null && blackListedProjects.contains( getId( project ) );
|
||||
}
|
||||
|
||||
public void blackList( MavenProject project )
|
||||
{
|
||||
if ( blackListedProjects == null )
|
||||
{
|
||||
blackListedProjects = new HashSet<String>();
|
||||
}
|
||||
|
||||
if ( blackListedProjects.add( getId( project ) ) && projectDependencyGraph != null )
|
||||
{
|
||||
for ( MavenProject downstreamProject : projectDependencyGraph.getDownstreamProjects( project, true ) )
|
||||
{
|
||||
blackListedProjects.add( getId( downstreamProject ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getId( MavenProject project )
|
||||
{
|
||||
return project.getGroupId() + ':' + project.getArtifactId() + ':' + project.getVersion();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package org.apache.maven.execution;
|
||||
|
||||
/*
|
||||
* 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 java.util.List;
|
||||
|
||||
import org.apache.maven.project.MavenProject;
|
||||
|
||||
/**
|
||||
* Describes the inter-dependencies between projects in the reactor.
|
||||
*
|
||||
* @author Benjamin Bentmann
|
||||
*/
|
||||
public interface ProjectDependencyGraph
|
||||
{
|
||||
|
||||
/**
|
||||
* Gets all projects in their intended build order, i.e. after topologically sorting the projects according to their
|
||||
* inter-dependencies.
|
||||
*
|
||||
* @return The projects in the build order, never {@code null}.
|
||||
*/
|
||||
List<MavenProject> getSortedProjects();
|
||||
|
||||
/**
|
||||
* Gets the downstream projects of the specified projects. A downstream project is a project that directly or
|
||||
* indirectly depends on the given project.
|
||||
*
|
||||
* @param project The project whose downstream projects should be retrieved, must not be {@code null}.
|
||||
* @param transitive A flag whether to retrieve all direct and indirect downstream projects or just the immediate
|
||||
* downstream projects.
|
||||
* @return The downstream projects in the build order, never {@code null}.
|
||||
*/
|
||||
List<MavenProject> getDownstreamProjects( MavenProject project, boolean transitive );
|
||||
|
||||
}
|
|
@ -58,11 +58,11 @@ public class ProjectSorter
|
|||
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
String id = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
|
||||
String id = getId( project );
|
||||
|
||||
if ( dag.getVertex( id ) != null )
|
||||
{
|
||||
MavenProject conflictingProject = (MavenProject) projectMap.get( id );
|
||||
MavenProject conflictingProject = projectMap.get( id );
|
||||
|
||||
throw new DuplicateProjectException( id, conflictingProject.getFile(), project.getFile(), "Project '" + id + "' is duplicated in the reactor" );
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ public class ProjectSorter
|
|||
|
||||
for ( MavenProject project : projects )
|
||||
{
|
||||
String id = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
|
||||
String id = getId( project );
|
||||
|
||||
for( Dependency dependency : project.getDependencies() )
|
||||
{
|
||||
|
@ -82,7 +82,7 @@ public class ProjectSorter
|
|||
|
||||
if ( dag.getVertex( dependencyId ) != null )
|
||||
{
|
||||
project.addProjectReference( (MavenProject) projectMap.get( dependencyId ) );
|
||||
project.addProjectReference( projectMap.get( dependencyId ) );
|
||||
|
||||
dag.addEdge( id, dependencyId );
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ public class ProjectSorter
|
|||
private void addEdgeWithParentCheck( Map<String,MavenProject> projectMap, String projectRefId, MavenProject project, String id )
|
||||
throws CycleDetectedException
|
||||
{
|
||||
MavenProject extProject = (MavenProject) projectMap.get( projectRefId );
|
||||
MavenProject extProject = projectMap.get( projectRefId );
|
||||
|
||||
if ( extProject == null )
|
||||
{
|
||||
|
@ -165,9 +165,9 @@ public class ProjectSorter
|
|||
{
|
||||
if ( topLevelProject == null )
|
||||
{
|
||||
for ( Iterator i = sortedProjects.iterator(); i.hasNext() && ( topLevelProject == null ); )
|
||||
for ( Iterator<MavenProject> i = sortedProjects.iterator(); i.hasNext() && ( topLevelProject == null ); )
|
||||
{
|
||||
MavenProject project = (MavenProject) i.next();
|
||||
MavenProject project = i.next();
|
||||
if ( project.isExecutionRoot() )
|
||||
{
|
||||
topLevelProject = project;
|
||||
|
@ -188,8 +188,14 @@ public class ProjectSorter
|
|||
return sortedProjects.size() > 1;
|
||||
}
|
||||
|
||||
List<String> getDependents( String id )
|
||||
public List<String> getDependents( String id )
|
||||
{
|
||||
return dag.getParentLabels( id );
|
||||
}
|
||||
}
|
||||
|
||||
public static String getId( MavenProject project )
|
||||
{
|
||||
return ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,8 +35,7 @@ import org.apache.maven.artifact.repository.ArtifactRepository;
|
|||
import org.apache.maven.artifact.repository.metadata.Metadata;
|
||||
import org.apache.maven.artifact.repository.metadata.RepositoryMetadataReadException;
|
||||
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
|
||||
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
|
||||
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.lifecycle.mapping.LifecycleMapping;
|
||||
import org.apache.maven.model.Dependency;
|
||||
|
@ -144,43 +143,27 @@ public class DefaultLifecycleExecutor
|
|||
|
||||
for ( MavenProject currentProject : session.getProjects() )
|
||||
{
|
||||
if ( session.isBlackListed( currentProject ) )
|
||||
{
|
||||
logger.info( "Skipping " + currentProject.getName() );
|
||||
logger.info( "This project has been banned from the build due to previous failures." );
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
logger.info( "Building " + currentProject.getName() );
|
||||
|
||||
try
|
||||
{
|
||||
session.setCurrentProject( currentProject );
|
||||
|
||||
MavenExecutionPlan executionPlan;
|
||||
|
||||
try
|
||||
{
|
||||
executionPlan = calculateExecutionPlan( session, goals.toArray( new String[] {} ) );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
session.getResult().addException( e );
|
||||
return;
|
||||
}
|
||||
MavenExecutionPlan executionPlan = calculateExecutionPlan( session, goals.toArray( new String[] {} ) );
|
||||
|
||||
//TODO: once we have calculated the build plan then we should accurately be able to download
|
||||
// the project dependencies. Having it happen in the plugin manager is a tangled mess. We can optimize this
|
||||
// later by looking at the build plan. Would be better to just batch download everything required by the reactor.
|
||||
|
||||
// mojoDescriptor.isDependencyResolutionRequired() is actually the scope of the dependency resolution required, not a boolean ... yah.
|
||||
try
|
||||
{
|
||||
projectDependenciesResolver.resolve( currentProject, executionPlan.getRequiredResolutionScopes(), session.getLocalRepository(), currentProject.getRemoteArtifactRepositories() );
|
||||
}
|
||||
catch ( ArtifactNotFoundException e )
|
||||
{
|
||||
session.getResult().addException( e );
|
||||
return;
|
||||
}
|
||||
catch ( ArtifactResolutionException e )
|
||||
{
|
||||
session.getResult().addException( e );
|
||||
return;
|
||||
}
|
||||
projectDependenciesResolver.resolve( currentProject, executionPlan.getRequiredResolutionScopes(), session.getLocalRepository(), currentProject.getRemoteArtifactRepositories() );
|
||||
|
||||
if ( logger.isDebugEnabled() )
|
||||
{
|
||||
|
@ -200,19 +183,35 @@ public class DefaultLifecycleExecutor
|
|||
|
||||
for ( MojoExecution mojoExecution : executionPlan.getExecutions() )
|
||||
{
|
||||
try
|
||||
{
|
||||
logger.info( executionDescription( mojoExecution, currentProject ) );
|
||||
pluginManager.executeMojo( session, mojoExecution );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
session.getResult().addException( e );
|
||||
return;
|
||||
}
|
||||
logger.info( executionDescription( mojoExecution, currentProject ) );
|
||||
pluginManager.executeMojo( session, mojoExecution );
|
||||
}
|
||||
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
session.getResult().addException( e );
|
||||
|
||||
if ( MavenExecutionRequest.REACTOR_FAIL_NEVER.equals( session.getReactorFailureBehavior() ) )
|
||||
{
|
||||
// continue the build
|
||||
}
|
||||
else if ( MavenExecutionRequest.REACTOR_FAIL_AT_END.equals( session.getReactorFailureBehavior() ) )
|
||||
{
|
||||
// continue the build but ban all projects that depend on the failed one
|
||||
session.blackList( currentProject );
|
||||
}
|
||||
else if ( MavenExecutionRequest.REACTOR_FAIL_FAST.equals( session.getReactorFailureBehavior() ) )
|
||||
{
|
||||
// abort the build
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "invalid reactor failure behavior "
|
||||
+ session.getReactorFailureBehavior() );
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
session.setCurrentProject( null );
|
||||
|
|
|
@ -192,7 +192,16 @@ public class MavenCli
|
|||
es.getException().printStackTrace();
|
||||
}
|
||||
|
||||
return 1;
|
||||
if ( MavenExecutionRequest.REACTOR_FAIL_NEVER.equals( request.getReactorFailureBehavior() ) )
|
||||
{
|
||||
System.out.println( "+ Build failures were ignored." );
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue