View Javadoc

1   package org.apache.maven.plugin.reactor;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.util.ArrayList;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Set;
27  
28  import org.apache.maven.plugin.MojoExecutionException;
29  import org.apache.maven.plugin.MojoFailureException;
30  import org.apache.maven.project.MavenProject;
31  import org.apache.maven.scm.ScmFile;
32  import org.apache.maven.scm.ScmFileSet;
33  import org.apache.maven.scm.ScmFileStatus;
34  import org.apache.maven.scm.command.status.StatusScmResult;
35  import org.apache.maven.scm.manager.ScmManager;
36  import org.apache.maven.scm.repository.ScmRepository;
37  import org.codehaus.plexus.util.StringUtils;
38  
39  /**
40   * Goal to build all projects that you personally have changed (according to SCM)
41   * 
42   * @author <a href="mailto:dfabulich@apache.org">Dan Fabulich</a>
43   * @goal make-scm-changes
44   * @aggregator
45   * @phase process-sources
46   */
47  public class MakeScmChanges
48      extends MakeDependentsMojo
49  {
50      /**
51       * The SCM connection/provider info.  Should be specified in your POM.
52       * @parameter expression="${make.scmConnection}" default-value="${project.scm.connection}"
53       * @required
54       */
55      String scmConnection;
56  
57      /**
58       * Ignore files in the "unknown" status (created but not added to source control)
59       * 
60       * @parameter expression="${make.ignoreUnknown}" default-value=true
61       */
62      private boolean ignoreUnknown = true;
63  
64      /**
65       * @component
66       */
67      ScmManager scmManager;
68  
69      public void execute()
70          throws MojoExecutionException, MojoFailureException
71      {
72          if ( collectedProjects.size() == 0 )
73          {
74              throw new NonReactorException();
75          }
76          if ( scmConnection == null )
77          {
78              throw new MojoFailureException("No SCM connection specified.  You must specify an SCM connection by adding a <connection> element to your <scm> element in your POM");
79          }
80          StatusScmResult result = null;
81          try
82          {
83              ScmRepository repository = scmManager.makeScmRepository( scmConnection );
84              result = scmManager.status( repository, new ScmFileSet( baseDir ) );
85          }
86          catch ( Exception e )
87          {
88              throw new MojoExecutionException( "Couldn't configure SCM repository: " + e.getLocalizedMessage(), e );
89          }
90  
91          List changedFiles = result.getChangedFiles();
92          
93          List projectDirectories = getProjectDirectories();
94          Set changedDirectories = new HashSet();
95          for ( int i = 0; i < changedFiles.size(); i++ )
96          {
97              ScmFile changedScmFile = (ScmFile) changedFiles.get( i );
98              getLog().debug( changedScmFile.toString() );
99              ScmFileStatus status = changedScmFile.getStatus();
100             if ( !status.isStatus() )
101             {
102                 getLog().debug( "Not a diff: " + status );
103                 continue;
104             }
105             if ( ignoreUnknown && ScmFileStatus.UNKNOWN.equals( status ) )
106             {
107                 getLog().debug( "Ignoring unknown" );
108                 continue;
109             }
110 
111             File changedFile = new File( changedScmFile.getPath() );
112             boolean found = false;
113             // TODO There's a cleverer/faster way to code this, right?  This is O(n^2)
114             for ( int j = 0; j < projectDirectories.size(); j++ )
115             {
116                 File projectDirectory = (File) projectDirectories.get( j );
117                 if ( changedFile.getAbsolutePath().startsWith( projectDirectory.getAbsolutePath() + File.separator ) )
118                 {
119                     String path = RelativePather.getRelativePath( baseDir, projectDirectory );
120                     if ( !changedDirectories.contains( path ) )
121                     {
122                         getLog().debug( "Including " + path );
123                     }
124                     changedDirectories.add( path );
125                     found = true;
126                     break;
127                 }
128             }
129             if ( !found )
130             {
131                 getLog().debug( "Couldn't find file in any reactor root: " + changedFile.getAbsolutePath() );
132             }
133         }
134         folderList = StringUtils.join( changedDirectories.iterator(), "," );
135         getLog().info( "Going to make dependents for: " + folderList );
136         super.execute();
137 
138     }
139 
140     private List getProjectDirectories()
141     {
142         List dirs = new ArrayList( collectedProjects.size() );
143         for ( int i = 0; i < collectedProjects.size(); i++ )
144         {
145             MavenProject mp = (MavenProject) collectedProjects.get( i );
146             dirs.add( mp.getFile().getParentFile() );
147         }
148         return dirs;
149     }
150 
151 }