You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by df...@apache.org on 2008/08/20 19:19:49 UTC

svn commit: r687388 - in /maven/components/branches/maven-2.1.x: maven-core/src/main/java/org/apache/maven/ maven-core/src/main/java/org/apache/maven/cli/ maven-core/src/main/java/org/apache/maven/execution/ maven-core/src/test/java/org/apache/maven/pl...

Author: dfabulich
Date: Wed Aug 20 10:19:21 2008
New Revision: 687388

URL: http://svn.apache.org/viewvc?rev=687388&view=rev
Log:
[MNG-2576] First cut at Make Like Reactor Mode

Added:
    maven/components/branches/maven-2.1.x/maven-project/src/main/java/org/apache/maven/project/MissingProjectException.java
Modified:
    maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/DefaultMaven.java
    maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/cli/MavenCli.java
    maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java
    maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java
    maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/ReactorManager.java
    maven/components/branches/maven-2.1.x/maven-core/src/test/java/org/apache/maven/plugin/PluginParameterExpressionEvaluatorTest.java
    maven/components/branches/maven-2.1.x/maven-project/src/main/java/org/apache/maven/project/ProjectSorter.java
    maven/components/branches/maven-2.1.x/maven-project/src/test/java/org/apache/maven/project/ProjectSorterTest.java

Modified: maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/DefaultMaven.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/DefaultMaven.java?rev=687388&r1=687387&r2=687388&view=diff
==============================================================================
--- maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/DefaultMaven.java (original)
+++ maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/DefaultMaven.java Wed Aug 20 10:19:21 2008
@@ -42,6 +42,7 @@
 import org.apache.maven.project.DuplicateProjectException;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.MavenProjectBuilder;
+import org.apache.maven.project.MissingProjectException;
 import org.apache.maven.project.ProjectBuildingException;
 import org.apache.maven.reactor.MavenExecutionException;
 import org.apache.maven.settings.Mirror;
@@ -299,14 +300,16 @@
         ReactorManager rm;
         try
         {
-            rm = new ReactorManager( projects );
-
-            String requestFailureBehavior = request.getFailureBehavior();
+            String resumeFrom = request.getResumeFrom();
+            
+            List projectList = request.getSelectedProjects();
+            
+            String makeBehavior = request.getMakeBehavior();
+            
+            rm = new ReactorManager( projects, projectList, resumeFrom, makeBehavior );
 
-            if ( requestFailureBehavior != null )
-            {
-                rm.setFailureBehavior( requestFailureBehavior );
-            }
+            rm.setFailureBehavior( request.getFailureBehavior() );
+            
         }
         catch ( CycleDetectedException e )
         {
@@ -317,6 +320,10 @@
         {
             throw new BuildFailureException( e.getMessage(), e );
         }
+        catch ( MissingProjectException e )
+        {
+            throw new BuildFailureException( e.getMessage(), e );
+        }
 
         if ( rm.hasMultipleProjects() )
         {

Modified: maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/cli/MavenCli.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/cli/MavenCli.java?rev=687388&r1=687387&r2=687388&view=diff
==============================================================================
--- maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/cli/MavenCli.java (original)
+++ maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/cli/MavenCli.java Wed Aug 20 10:19:21 2008
@@ -55,6 +55,7 @@
 import org.codehaus.plexus.logging.Logger;
 import org.codehaus.plexus.logging.LoggerManager;
 import org.codehaus.plexus.util.Os;
+import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.cli.CommandLineUtils;
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 
@@ -62,6 +63,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
@@ -473,6 +475,32 @@
         {
             request.setPomFile( commandLine.getOptionValue( CLIManager.ALTERNATE_POM_FILE ) );
         }
+        
+        if ( commandLine.hasOption( CLIManager.RESUME_FROM ) )
+        {
+            request.setResumeFrom( commandLine.getOptionValue( CLIManager.RESUME_FROM ) );
+        }
+        
+        if ( commandLine.hasOption( CLIManager.PROJECT_LIST ) )
+        {
+            String projectList = commandLine.getOptionValue( CLIManager.PROJECT_LIST );
+            String[] projects = StringUtils.split( projectList, "," );
+            request.setSelectedProjects( Arrays.asList( projects ) );
+        }
+        
+        if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) && !commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
+        {
+            request.setMakeBehavior( ReactorManager.MAKE_MODE );
+        }
+        else if ( !commandLine.hasOption( CLIManager.ALSO_MAKE )
+            && commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
+        {
+            request.setMakeBehavior( ReactorManager.MAKE_DEPENDENTS_MODE );
+        }
+        if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) && commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
+        {
+            request.setMakeBehavior( ReactorManager.MAKE_BOTH_MODE );
+        }
     }
 
     private static Maven createMavenInstance( boolean interactive )
@@ -721,6 +749,14 @@
         private static final String FAIL_AT_END = "fae";
 
         private static final String FAIL_NEVER = "fn";
+        
+        private static final String RESUME_FROM = "rf";
+        
+        private static final String PROJECT_LIST = "pl";
+        
+        private static final String ALSO_MAKE = "am";
+        
+        private static final String ALSO_MAKE_DEPENDENTS = "amd";
 
         public CLIManager()
         {
@@ -792,6 +828,14 @@
             options.addOption(
                               OptionBuilder.withLongOpt( "show-version" ).withDescription( "Display version information WITHOUT stopping build" ).create(
                                   SHOW_VERSION ) );
+            options.addOption( OptionBuilder.withLongOpt( "resume-from" ).hasArg().withDescription( "Resume reactor from specified project" ).create(
+                                  RESUME_FROM ) );
+            options.addOption( OptionBuilder.withLongOpt( "projects" ).withDescription(
+                "Build specified reactor projects instead of all projects" ).hasArg().create( PROJECT_LIST ) );
+            options.addOption( OptionBuilder.withLongOpt( "also-make" ).withDescription(
+                "If project list is specified, also build projects required by the list" ).create( ALSO_MAKE ) );
+            options.addOption( OptionBuilder.withLongOpt( "also-make-dependents" ).withDescription(
+                "If project list is specified, also build projects that depend on projects on the list" ).create( ALSO_MAKE_DEPENDENTS ) );
         }
 
         public CommandLine parse( String[] args )

Modified: maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java?rev=687388&r1=687387&r2=687388&view=diff
==============================================================================
--- maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java (original)
+++ maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java Wed Aug 20 10:19:21 2008
@@ -70,6 +70,12 @@
     private final Date startTime;
 
     private final boolean showErrors;
+    
+    private String makeBehavior;
+    
+    private String resumeFrom;
+    
+    private List selectedProjects;
 
     public DefaultMavenExecutionRequest( ArtifactRepository localRepository, Settings settings,
                                          EventDispatcher eventDispatcher, List goals, String baseDirectory,
@@ -218,4 +224,35 @@
 
         return config;
     }
+    
+    public String getMakeBehavior()
+    {
+        return makeBehavior;
+    }
+
+    public void setMakeBehavior( String makeBehavior )
+    {
+        this.makeBehavior = makeBehavior;
+    }
+
+    public String getResumeFrom()
+    {
+        return resumeFrom;
+    }
+
+    public void setResumeFrom( String resumeFrom )
+    {
+        this.resumeFrom = resumeFrom;
+    }
+
+    public List getSelectedProjects()
+    {
+        return selectedProjects;
+    }
+
+    public void setSelectedProjects( List selectedProjects )
+    {
+        this.selectedProjects = selectedProjects;
+    }
+
 }

Modified: maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java?rev=687388&r1=687387&r2=687388&view=diff
==============================================================================
--- maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java (original)
+++ maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java Wed Aug 20 10:19:21 2008
@@ -60,6 +60,18 @@
 
     boolean isReactorActive();
 
+    void setResumeFrom( String resumeFrom );
+
+    String getResumeFrom();
+    
+    void setSelectedProjects( List projects );
+    
+    List getSelectedProjects();
+    
+    void setMakeBehavior( String makeBehavior );
+    
+    String getMakeBehavior();
+    
     void setPomFile( String pomFile );
 
     String getPomFile();

Modified: maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/ReactorManager.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/ReactorManager.java?rev=687388&r1=687387&r2=687388&view=diff
==============================================================================
--- maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/ReactorManager.java (original)
+++ maven/components/branches/maven-2.1.x/maven-core/src/main/java/org/apache/maven/execution/ReactorManager.java Wed Aug 20 10:19:21 2008
@@ -24,6 +24,7 @@
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
 import org.apache.maven.project.DuplicateProjectException;
 import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.MissingProjectException;
 import org.apache.maven.project.ProjectSorter;
 import org.codehaus.plexus.util.dag.CycleDetectedException;
 
@@ -41,6 +42,13 @@
 
     public static final String FAIL_NEVER = "fail-never";
 
+    public static final String MAKE_MODE = "make";
+
+    public static final String MAKE_DEPENDENTS_MODE = "make-dependents";
+
+    // make projects that depend on me, and projects that I depend on
+    public static final String MAKE_BOTH_MODE = "make-both";
+    
     private List blackList = new ArrayList();
 
     private Map buildFailuresByProject = new HashMap();
@@ -54,10 +62,42 @@
     private Map buildSuccessesByProject = new HashMap();
 
     public ReactorManager( List projects )
-        throws CycleDetectedException, DuplicateProjectException
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
     {
         this.sorter = new ProjectSorter( projects );
     }
+    
+    public ReactorManager( List projects, List selectedProjects, String resumeFrom, String makeBehavior )
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
+    {
+        boolean make, makeDependents;
+        if ( makeBehavior == null )
+        {
+            make = false;
+            makeDependents = false;
+        }
+        else if ( MAKE_MODE.equals( makeBehavior ) )
+        {
+            make = true;
+            makeDependents = false;
+        }
+        else if ( MAKE_DEPENDENTS_MODE.equals( makeBehavior ) )
+        {
+            make = false;
+            makeDependents = true;
+        }
+        else if ( MAKE_BOTH_MODE.equals( makeBehavior ) )
+        {
+            make = true;
+            makeDependents = true;
+        }
+        else
+        {
+            throw new IllegalArgumentException( "Invalid make behavior (must be one of: \'" + MAKE_MODE + "\', \'"
+                + MAKE_DEPENDENTS_MODE + "\', \'" + MAKE_BOTH_MODE + "\')." );
+        }
+        this.sorter = new ProjectSorter( projects, selectedProjects, resumeFrom, make, makeDependents );
+    }
 
     public Map getPluginContext( PluginDescriptor plugin, MavenProject project )
     {
@@ -82,6 +122,11 @@
 
     public void setFailureBehavior( String failureBehavior )
     {
+        if ( failureBehavior == null )
+        {
+            this.failureBehavior = FAIL_FAST; // default
+            return;
+        }
         if ( FAIL_FAST.equals( failureBehavior ) || FAIL_AT_END.equals( failureBehavior ) ||
             FAIL_NEVER.equals( failureBehavior ) )
         {

Modified: maven/components/branches/maven-2.1.x/maven-core/src/test/java/org/apache/maven/plugin/PluginParameterExpressionEvaluatorTest.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.1.x/maven-core/src/test/java/org/apache/maven/plugin/PluginParameterExpressionEvaluatorTest.java?rev=687388&r1=687387&r2=687388&view=diff
==============================================================================
--- maven/components/branches/maven-2.1.x/maven-core/src/test/java/org/apache/maven/plugin/PluginParameterExpressionEvaluatorTest.java (original)
+++ maven/components/branches/maven-2.1.x/maven-core/src/test/java/org/apache/maven/plugin/PluginParameterExpressionEvaluatorTest.java Wed Aug 20 10:19:21 2008
@@ -34,6 +34,7 @@
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
 import org.apache.maven.project.DuplicateProjectException;
 import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.MissingProjectException;
 import org.apache.maven.settings.Settings;
 import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.PlexusTestCase;
@@ -201,7 +202,7 @@
     }
 
     private static MavenSession createSession( PlexusContainer container, ArtifactRepository repo )
-        throws CycleDetectedException, DuplicateProjectException
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
     {
         return new MavenSession( container, new Settings(), repo, new DefaultEventDispatcher(),
                                  new ReactorManager( Collections.EMPTY_LIST ), Collections.EMPTY_LIST, ".",

Added: maven/components/branches/maven-2.1.x/maven-project/src/main/java/org/apache/maven/project/MissingProjectException.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.1.x/maven-project/src/main/java/org/apache/maven/project/MissingProjectException.java?rev=687388&view=auto
==============================================================================
--- maven/components/branches/maven-2.1.x/maven-project/src/main/java/org/apache/maven/project/MissingProjectException.java (added)
+++ maven/components/branches/maven-2.1.x/maven-project/src/main/java/org/apache/maven/project/MissingProjectException.java Wed Aug 20 10:19:21 2008
@@ -0,0 +1,41 @@
+package org.apache.maven.project;
+
+
+/*
+ * 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.
+ */
+
+/**
+ * Exception that occurs when the user has identifed a project to make, but that project doesn't exist.
+ * 
+ * @author <a href="mailto:dfabulich@apache.org">Dan Fabulich</a>
+ * @version $Id: DuplicateProjectException.java 640549 2008-03-24 20:05:11Z bentmann $
+ */
+public class MissingProjectException
+    extends Exception
+{
+    public MissingProjectException( String message )
+    {
+        super( message );
+    }
+    
+    public MissingProjectException( String message, Exception e )
+    {
+        super( message, e );
+    }
+}

Modified: maven/components/branches/maven-2.1.x/maven-project/src/main/java/org/apache/maven/project/ProjectSorter.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.1.x/maven-project/src/main/java/org/apache/maven/project/ProjectSorter.java?rev=687388&r1=687387&r2=687388&view=diff
==============================================================================
--- maven/components/branches/maven-2.1.x/maven-project/src/main/java/org/apache/maven/project/ProjectSorter.java (original)
+++ maven/components/branches/maven-2.1.x/maven-project/src/main/java/org/apache/maven/project/ProjectSorter.java Wed Aug 20 10:19:21 2008
@@ -19,6 +19,17 @@
  * under the License.
  */
 
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.maven.artifact.ArtifactUtils;
 import org.apache.maven.model.Dependency;
 import org.apache.maven.model.Extension;
@@ -27,13 +38,7 @@
 import org.codehaus.plexus.util.dag.CycleDetectedException;
 import org.codehaus.plexus.util.dag.DAG;
 import org.codehaus.plexus.util.dag.TopologicalSorter;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import org.codehaus.plexus.util.dag.Vertex;
 
 /**
  * Sort projects by dependencies.
@@ -44,6 +49,8 @@
 public class ProjectSorter
 {
     private final DAG dag;
+    
+    private final Map projectMap;
 
     private final List sortedProjects;
 
@@ -60,13 +67,20 @@
      * <li>do a topo sort on the graph that remains.</li>
      * </ul>
      * @throws DuplicateProjectException if any projects are duplicated by id
+     * @throws MissingProjectException 
      */
     public ProjectSorter( List projects )
-        throws CycleDetectedException, DuplicateProjectException
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
+    {
+        this( projects, null, null, false, false );
+    }
+    
+    public ProjectSorter( List projects, List selectedProjectNames, String resumeFrom, boolean make, boolean makeDependents )
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
     {
         dag = new DAG();
 
-        Map projectMap = new HashMap();
+        projectMap = new HashMap();
 
         for ( Iterator i = projects.iterator(); i.hasNext(); )
         {
@@ -167,10 +181,130 @@
 
             sortedProjects.add( projectMap.get( id ) );
         }
+        
+        // TODO: !![jc; 28-jul-2005] check this; if we're using '-r' and there are aggregator tasks, this will result in weirdness.
+        for ( Iterator i = sortedProjects.iterator(); i.hasNext() && topLevelProject == null; )
+        {
+            MavenProject project = (MavenProject) i.next();
+            if ( project.isExecutionRoot() )
+            {
+                topLevelProject = project;
+            }
+        }
+        
+        sortedProjects = applyMakeFilter( sortedProjects, dag, projectMap, topLevelProject, selectedProjectNames, make, makeDependents );
+        
+        resumeFrom( resumeFrom, sortedProjects, projectMap, topLevelProject );
 
         this.sortedProjects = Collections.unmodifiableList( sortedProjects );
     }
 
+    // make selected projects and possibly projects they depend on, or projects that depend on them 
+    private static List applyMakeFilter( List sortedProjects, DAG dag, Map projectMap, MavenProject topLevelProject, List selectedProjectNames, boolean make, boolean makeDependents ) throws MissingProjectException
+    {
+        if ( selectedProjectNames == null ) return sortedProjects;
+        
+        MavenProject[] selectedProjects = new MavenProject[selectedProjectNames.size()];
+        for ( int i = 0; i < selectedProjects.length; i++ )
+        {
+            selectedProjects[i] = findProject( (String) selectedProjectNames.get( i ), projectMap, topLevelProject );
+        }
+        Set projectsToMake = new HashSet( Arrays.asList( selectedProjects ) );
+        for ( int i = 0; i < selectedProjects.length; i++ )
+        {
+            MavenProject project = selectedProjects[i];
+            String id = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
+            Vertex v = dag.getVertex( id );
+            if ( make )
+            {
+                gatherDescendents ( v, projectMap, projectsToMake, new HashSet() );
+            }
+            if ( makeDependents )
+            {
+                gatherAncestors ( v, projectMap, projectsToMake, new HashSet() );
+            }
+        }
+        for ( Iterator i = sortedProjects.iterator(); i.hasNext(); )
+        {
+            MavenProject project = (MavenProject) i.next();
+            if ( !projectsToMake.contains( project ) )
+            {
+                i.remove();
+            }
+        }
+        return sortedProjects;
+    }
+    
+    private static void resumeFrom( String resumeFrom, List sortedProjects, Map projectMap, MavenProject topLevelProject ) throws MissingProjectException
+    {
+        if ( resumeFrom == null ) return;
+        MavenProject resumeFromProject = findProject( resumeFrom, projectMap, topLevelProject );
+        for ( Iterator i = sortedProjects.iterator(); i.hasNext(); )
+        {
+            MavenProject project = (MavenProject) i.next();
+            if ( resumeFromProject.equals( project ) ) break;
+            i.remove();
+        }
+        if ( sortedProjects.isEmpty() )
+        {
+            throw new MissingProjectException( "Couldn't resume, project was not scheduled to run: " + resumeFrom );
+        }
+    }
+    
+    private static MavenProject findProject( String projectName, Map projectMap, MavenProject topLevelProject ) throws MissingProjectException
+    {
+        MavenProject project = (MavenProject) projectMap.get( projectName );
+        if ( project != null ) return project;
+        // in that case, it must be a file path
+        File baseDir;
+        if ( topLevelProject == null ) {
+            baseDir = new File( System.getProperty( "user.dir" ) );
+        } else {
+            baseDir = topLevelProject.getBasedir();
+            // or should this be .getFile().getParentFile() ?
+        }
+        
+        File projectDir = new File( baseDir, projectName );
+        if ( !projectDir.exists() ) {
+            throw new MissingProjectException( "Couldn't find specified project dir: " + projectDir.getAbsolutePath() );
+        }
+        if ( !projectDir.isDirectory() ) {
+            throw new MissingProjectException( "Couldn't find specified project dir (not a directory): " + projectDir.getAbsolutePath() );
+        }
+        
+        for ( Iterator i = projectMap.values().iterator(); i.hasNext(); )
+        {
+            project = (MavenProject) i.next();
+            if ( projectDir.equals( project.getFile().getParentFile() ) ) return project;
+        }
+        
+        throw new MissingProjectException( "Couldn't find specified project in module list: " + projectDir.getAbsolutePath() );
+    }
+    
+    private static void gatherDescendents ( Vertex v, Map projectMap, Set out, Set visited )
+    {
+        if ( visited.contains( v ) ) return;
+        visited.add( v );
+        out.add( projectMap.get( v.getLabel() ) );
+        for ( Iterator i = v.getChildren().iterator(); i.hasNext(); )
+        {
+            Vertex child = (Vertex) i.next();
+            gatherDescendents( child, projectMap, out, visited );
+        }
+    }
+    
+    private static void gatherAncestors ( Vertex v, Map projectMap, Set out, Set visited )
+    {
+        if ( visited.contains( v ) ) return;
+        visited.add( v );
+        out.add( projectMap.get( v.getLabel() ) );
+        for ( Iterator i = v.getParents().iterator(); i.hasNext(); )
+        {
+            Vertex parent = (Vertex) i.next();
+            gatherAncestors( parent, projectMap, out, visited );
+        }
+    }
+    
     private void addEdgeWithParentCheck( Map projectMap, String projectRefId, MavenProject project, String id )
         throws CycleDetectedException
     {
@@ -195,21 +329,8 @@
         }
     }
 
-    // TODO: !![jc; 28-jul-2005] check this; if we're using '-r' and there are aggregator tasks, this will result in weirdness.
     public MavenProject getTopLevelProject()
     {
-        if ( topLevelProject == null )
-        {
-            for ( Iterator i = sortedProjects.iterator(); i.hasNext() && topLevelProject == null; )
-            {
-                MavenProject project = (MavenProject) i.next();
-                if ( project.isExecutionRoot() )
-                {
-                    topLevelProject = project;
-                }
-            }
-        }
-
         return topLevelProject;
     }
 
@@ -227,4 +348,14 @@
     {
         return dag.getParentLabels( id );
     }
+    
+    public DAG getDAG()
+    {
+        return dag;
+    }
+    
+    public Map getProjectMap()
+    {
+        return projectMap;
+    }
 }

Modified: maven/components/branches/maven-2.1.x/maven-project/src/test/java/org/apache/maven/project/ProjectSorterTest.java
URL: http://svn.apache.org/viewvc/maven/components/branches/maven-2.1.x/maven-project/src/test/java/org/apache/maven/project/ProjectSorterTest.java?rev=687388&r1=687387&r2=687388&view=diff
==============================================================================
--- maven/components/branches/maven-2.1.x/maven-project/src/test/java/org/apache/maven/project/ProjectSorterTest.java (original)
+++ maven/components/branches/maven-2.1.x/maven-project/src/test/java/org/apache/maven/project/ProjectSorterTest.java Wed Aug 20 10:19:21 2008
@@ -28,6 +28,7 @@
 import org.codehaus.plexus.util.dag.CycleDetectedException;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
@@ -40,9 +41,145 @@
 public class ProjectSorterTest
     extends TestCase
 {
+
+    public void testBasicSingleProject()
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
+    {
+        MavenProject project = createProject( "group", "artifactA", "1.0" );
+
+        List projects = new ProjectSorter( Collections.singletonList( project ) ).getSortedProjects();
+        
+        assertEquals( "Wrong number of projects: " + projects, 1, projects.size() );
+        assertEquals( "Didn't match project", project, projects.get( 0 ) );
+    }
+    
+    public void testBasicMultiProject()
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
+    {
+        MavenProject projectA = createProject( "group", "artifactA", "1.0" );
+        MavenProject projectB = createProject( "group", "artifactB", "1.0" );
+        MavenProject projectC = createProject( "group", "artifactC", "1.0" );
+        
+        projectA.getDependencies().add( createDependency( projectB ) );
+        projectB.getDependencies().add( createDependency( projectC ) );
+        
+        List projects = Arrays.asList( new Object[] { projectA, projectB, projectC} );
+
+        projects = new ProjectSorter( projects ).getSortedProjects();
+
+        assertEquals( "Wrong number of projects: " + projects, 3, projects.size() );
+        assertEquals( "Didn't match project", projectC, projects.get( 0 ) );
+        assertEquals( "Didn't match project", projectB, projects.get( 1 ) );
+        assertEquals( "Didn't match project", projectA, projects.get( 2 ) );
+    }
+
+    public void testResumeFrom()
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
+    {
+        MavenProject projectA = createProject( "group", "artifactA", "1.0" );
+        MavenProject projectB = createProject( "group", "artifactB", "1.0" );
+        MavenProject projectC = createProject( "group", "artifactC", "1.0" );
+
+        projectA.getDependencies().add( createDependency( projectB ) );
+        projectB.getDependencies().add( createDependency( projectC ) );
+
+        List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
+
+        projects = new ProjectSorter( projects, null, "group:artifactB", false, false ).getSortedProjects();
+
+        assertEquals( "Wrong number of projects: " + projects, 2, projects.size() );
+        assertEquals( "Didn't match project", projectB, projects.get( 0 ) );
+        assertEquals( "Didn't match project", projectA, projects.get( 1 ) );
+    }
+
+    public void testSelectedProjects()
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
+    {
+        MavenProject projectA = createProject( "group", "artifactA", "1.0" );
+        MavenProject projectB = createProject( "group", "artifactB", "1.0" );
+        MavenProject projectC = createProject( "group", "artifactC", "1.0" );
+
+        projectA.getDependencies().add( createDependency( projectB ) );
+        projectB.getDependencies().add( createDependency( projectC ) );
+
+        List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
+        List selectedProjects = Arrays.asList( new Object[] { "group:artifactB" } );
+
+        projects = new ProjectSorter( projects, selectedProjects, null, false, false ).getSortedProjects();
+
+        assertEquals( "Wrong number of projects: " + projects, 1, projects.size() );
+        assertEquals( "Didn't match project", projectB, projects.get( 0 ) );
+    }
+
+    public void testMake()
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
+    {
+        MavenProject projectA = createProject( "group", "artifactA", "1.0" );
+        MavenProject projectB = createProject( "group", "artifactB", "1.0" );
+        MavenProject projectC = createProject( "group", "artifactC", "1.0" );
+
+        projectA.getDependencies().add( createDependency( projectB ) );
+        projectB.getDependencies().add( createDependency( projectC ) );
+
+        List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
+        List selectedProjects = Arrays.asList( new Object[] { "group:artifactB" } );
+
+        projects = new ProjectSorter( projects, selectedProjects, null, true/* make */, false ).getSortedProjects();
+
+        assertEquals( "Wrong number of projects: " + projects, 2, projects.size() );
+        assertEquals( "Didn't match project", projectC, projects.get( 0 ) );
+        assertEquals( "Didn't match project", projectB, projects.get( 1 ) );
+    }
+
+    public void testMakeDependents()
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
+    {
+        MavenProject projectA = createProject( "group", "artifactA", "1.0" );
+        MavenProject projectB = createProject( "group", "artifactB", "1.0" );
+        MavenProject projectC = createProject( "group", "artifactC", "1.0" );
+
+        projectA.getDependencies().add( createDependency( projectB ) );
+        projectB.getDependencies().add( createDependency( projectC ) );
+
+        List projects = Arrays.asList( new Object[] { projectA, projectB, projectC } );
+        List selectedProjects = Arrays.asList( new Object[] { "group:artifactB" } );
+
+        projects = new ProjectSorter( projects, selectedProjects, null, false/* make */, true/*makeDependents*/ ).getSortedProjects();
+
+        assertEquals( "Wrong number of projects: " + projects, 2, projects.size() );
+        assertEquals( "Didn't match project", projectB, projects.get( 0 ) );
+        assertEquals( "Didn't match project", projectA, projects.get( 1 ) );
+    }
+
+    public void testMakeBoth()
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
+    {
+        MavenProject projectA = createProject( "group", "artifactA", "1.0" );
+        MavenProject projectB = createProject( "group", "artifactB", "1.0" );
+        MavenProject projectC = createProject( "group", "artifactC", "1.0" );
+        MavenProject projectD = createProject( "group", "artifactD", "1.0" );
+        MavenProject projectE = createProject( "group", "artifactE", "1.0" );
+
+        projectA.getDependencies().add( createDependency( projectB ) );
+        projectB.getDependencies().add( createDependency( projectC ) );
+        projectD.getDependencies().add( createDependency( projectE ) );
+        projectE.getDependencies().add( createDependency( projectB ) );
+
+        List projects = Arrays.asList( new Object[] { projectA, projectB, projectC, projectD, projectE } );
+        List selectedProjects = Arrays.asList( new Object[] { "group:artifactE" } );
+
+        projects =
+            new ProjectSorter( projects, selectedProjects, null, true/* make */, true/* makeDependents */).getSortedProjects();
+
+        assertEquals( "Wrong number of projects: " + projects, 4, projects.size() );
+        assertEquals( "Didn't match project", projectC, projects.get( 0 ) );
+        assertEquals( "Didn't match project", projectB, projects.get( 1 ) );
+        assertEquals( "Didn't match project", projectE, projects.get( 2 ) );
+        assertEquals( "Didn't match project", projectD, projects.get( 3 ) );
+    }
     
     public void testShouldNotFailWhenProjectReferencesNonExistentProject()
-        throws CycleDetectedException, DuplicateProjectException
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
     {
         MavenProject project = createProject( "group", "artifact", "1.0" );
         Model model = project.getModel();
@@ -67,7 +204,7 @@
     }
     
     public void testMatchingArtifactIdsDifferentGroupIds()
-        throws CycleDetectedException, DuplicateProjectException
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
     {
         List projects = new ArrayList();
         MavenProject project1 = createProject( "groupId1", "artifactId", "1.0" );
@@ -83,7 +220,7 @@
     }
 
     public void testMatchingGroupIdsDifferentArtifactIds()
-        throws CycleDetectedException, DuplicateProjectException
+        throws CycleDetectedException, DuplicateProjectException, MissingProjectException
     {
         List projects = new ArrayList();
         MavenProject project1 = createProject( "groupId", "artifactId1", "1.0" );
@@ -99,7 +236,7 @@
     }
 
     public void testMatchingIdsAndVersions()
-        throws CycleDetectedException
+        throws CycleDetectedException, MissingProjectException
     {
         List projects = new ArrayList();
         MavenProject project1 = createProject( "groupId", "artifactId", "1.0" );
@@ -120,7 +257,7 @@
     }
 
     public void testMatchingIdsAndDifferentVersions()
-        throws CycleDetectedException
+        throws CycleDetectedException, MissingProjectException
     {
         List projects = new ArrayList();
         MavenProject project1 = createProject( "groupId", "artifactId", "1.0" );