Coverage Report - org.apache.maven.shared.release.phase.CheckoutProjectFromScm
 
Classes in this File Line Coverage Branch Coverage Complexity
CheckoutProjectFromScm
63%
53/84
35%
10/28
11
 
 1  
 package org.apache.maven.shared.release.phase;
 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.io.IOException;
 24  
 import java.util.List;
 25  
 
 26  
 import org.apache.maven.project.MavenProject;
 27  
 import org.apache.maven.scm.ScmException;
 28  
 import org.apache.maven.scm.ScmFileSet;
 29  
 import org.apache.maven.scm.ScmTag;
 30  
 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
 31  
 import org.apache.maven.scm.manager.NoSuchScmProviderException;
 32  
 import org.apache.maven.scm.provider.ScmProvider;
 33  
 import org.apache.maven.scm.repository.ScmRepository;
 34  
 import org.apache.maven.scm.repository.ScmRepositoryException;
 35  
 import org.apache.maven.shared.release.ReleaseExecutionException;
 36  
 import org.apache.maven.shared.release.ReleaseFailureException;
 37  
 import org.apache.maven.shared.release.ReleaseResult;
 38  
 import org.apache.maven.shared.release.config.ReleaseDescriptor;
 39  
 import org.apache.maven.shared.release.env.ReleaseEnvironment;
 40  
 import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
 41  
 import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
 42  
 import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
 43  
 import org.apache.maven.shared.release.util.ReleaseUtil;
 44  
 import org.codehaus.plexus.util.FileUtils;
 45  
 import org.codehaus.plexus.util.StringUtils;
 46  
 
 47  
 /**
 48  
  * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
 49  
  * @version $Id: CheckoutProjectFromScm.java 1332838 2012-05-01 21:21:47Z rfscholte $
 50  
  * @plexus.component role="org.apache.maven.shared.release.phase.ReleasePhase" role-hint="checkout-project-from-scm"
 51  
  */
 52  64
 public class CheckoutProjectFromScm
 53  
     extends AbstractReleasePhase
 54  
 {
 55  
     /**
 56  
      * Tool that gets a configured SCM repository from release configuration.
 57  
      *
 58  
      * @plexus.requirement
 59  
      */
 60  
     private ScmRepositoryConfigurator scmRepositoryConfigurator;
 61  
 
 62  
     /** {@inheritDoc}  */
 63  
     public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
 64  
                                   List<MavenProject> reactorProjects )
 65  
             throws ReleaseExecutionException, ReleaseFailureException
 66  
     {
 67  26
         ReleaseResult releaseResult = null;
 68  
 
 69  26
         if ( releaseDescriptor.isLocalCheckout() )
 70  
         {
 71  
             // in the release phase we have to change the checkout URL
 72  
             // to do a local checkout instead of going over the network.
 73  
 
 74  
             // the first step is a bit tricky, we need to know which provider! like e.g. "scm:jgit:http://"
 75  
             // the offset of 4 is because 'scm:' has 4 characters...
 76  0
             String providerPart = releaseDescriptor.getScmSourceUrl()
 77  
                     .substring( 0, releaseDescriptor.getScmSourceUrl().indexOf( ':', 4 ) );
 78  
 
 79  0
             String scmPath = releaseDescriptor.getWorkingDirectory();
 80  
 
 81  
             // now we iteratively try to checkout.
 82  
             // if the local checkout fails, then we might be in a subdirectory
 83  
             // and need to walk a few directories up.
 84  
             do
 85  
             {
 86  
                 try
 87  
                 {
 88  0
                     if ( scmPath.startsWith( "/" ) )
 89  
                     {
 90  
                         // cut off the first '/'
 91  0
                         scmPath = scmPath.substring( 1 );
 92  
                     }
 93  
 
 94  0
                     String scmUrl = providerPart + ":file:///" + scmPath;
 95  0
                     releaseDescriptor.setScmSourceUrl( scmUrl );
 96  0
                     getLogger().info( "Performing a LOCAL checkout from " + releaseDescriptor.getScmSourceUrl() );
 97  
 
 98  0
                     releaseResult = performCheckout( releaseDescriptor, releaseEnvironment, reactorProjects );
 99  
                 }
 100  0
                 catch ( ScmException scmEx )
 101  
                 {
 102  
                     // the checkout from _this_ directory failed
 103  0
                     releaseResult = null;
 104  0
                 }
 105  
 
 106  0
                 if ( releaseResult == null || releaseResult.getResultCode() == ReleaseResult.ERROR )
 107  
                 {
 108  
                     // this means that there is no SCM repo in this directory
 109  
                     // thus we try to step one directory up
 110  0
                     releaseResult = null;
 111  
 
 112  
                     // remove last sub-directory path
 113  0
                     int lastSlashPos = scmPath.lastIndexOf( File.separator );
 114  0
                     if ( lastSlashPos > 0 )
 115  
                     {
 116  0
                         scmPath = scmPath.substring( 0, lastSlashPos );
 117  
                     }
 118  
                     else
 119  
                     {
 120  0
                         throw new ReleaseExecutionException( "could not perform a local checkout" );
 121  
                     }
 122  
                 }
 123  
             }
 124  0
             while ( releaseResult == null );
 125  0
         }
 126  
         else
 127  
         {
 128  
             // when there is no localCheckout, then we just do a standard SCM checkout.
 129  
             try
 130  
             {
 131  26
                 releaseResult =  performCheckout( releaseDescriptor, releaseEnvironment, reactorProjects );
 132  
             }
 133  2
             catch ( ScmException e )
 134  
             {
 135  2
                 releaseResult = new ReleaseResult();
 136  2
                 releaseResult.setResultCode( ReleaseResult.ERROR );
 137  2
                 logError( releaseResult, e.getMessage() );
 138  
 
 139  2
                 throw new ReleaseExecutionException( "An error is occurred in the checkout process: "
 140  
                                                      + e.getMessage(), e );
 141  18
             }
 142  
 
 143  
         }
 144  
 
 145  18
         return releaseResult;
 146  
     }
 147  
 
 148  
 
 149  
     private ReleaseResult performCheckout( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
 150  
                                   List<MavenProject> reactorProjects )
 151  
         throws ReleaseExecutionException, ReleaseFailureException, ScmException
 152  
     {
 153  26
         ReleaseResult result = new ReleaseResult();
 154  
 
 155  26
         logInfo( result, "Checking out the project to perform the release ..." );
 156  
 
 157  
         ScmRepository repository;
 158  
         ScmProvider provider;
 159  
 
 160  
         try
 161  
         {
 162  26
             repository = scmRepositoryConfigurator.getConfiguredRepository( releaseDescriptor,
 163  
                                                                             releaseEnvironment.getSettings() );
 164  
 
 165  22
             provider = scmRepositoryConfigurator.getRepositoryProvider( repository );
 166  
         }
 167  2
         catch ( ScmRepositoryException e )
 168  
         {
 169  2
             result.setResultCode( ReleaseResult.ERROR );
 170  2
             logError( result, e.getMessage() );
 171  
 
 172  2
             throw new ReleaseScmRepositoryException( e.getMessage(), e.getValidationMessages() );
 173  
         }
 174  2
         catch ( NoSuchScmProviderException e )
 175  
         {
 176  2
             result.setResultCode( ReleaseResult.ERROR );
 177  2
             logError( result, e.getMessage() );
 178  
 
 179  2
             throw new ReleaseExecutionException( "Unable to configure SCM repository: " + e.getMessage(), e );
 180  22
         }
 181  
 
 182  22
         MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
 183  
         // TODO: sanity check that it is not . or .. or lower
 184  
         File checkoutDirectory;
 185  22
         if ( StringUtils.isEmpty( releaseDescriptor.getCheckoutDirectory() ) )
 186  
         {
 187  0
             checkoutDirectory = new File( rootProject.getFile().getParentFile(), "target/checkout" );
 188  0
             releaseDescriptor.setCheckoutDirectory( checkoutDirectory.getAbsolutePath() );
 189  
         }
 190  
         else
 191  
         {
 192  22
             checkoutDirectory = new File( releaseDescriptor.getCheckoutDirectory() );
 193  
         }
 194  
 
 195  22
         if ( checkoutDirectory.exists() )
 196  
         {
 197  
             try
 198  
             {
 199  22
                 FileUtils.deleteDirectory( checkoutDirectory );
 200  
             }
 201  0
             catch ( IOException e )
 202  
             {
 203  0
                 result.setResultCode( ReleaseResult.ERROR );
 204  0
                 logError( result, e.getMessage() );
 205  
 
 206  0
                 throw new ReleaseExecutionException( "Unable to remove old checkout directory: " + e.getMessage(), e );
 207  22
             }
 208  
         }
 209  
 
 210  22
         checkoutDirectory.mkdirs();
 211  
 
 212  
         CheckOutScmResult scmResult;
 213  
 
 214  22
         scmResult = provider.checkOut( repository, new ScmFileSet( checkoutDirectory ),
 215  
                                        new ScmTag( releaseDescriptor.getScmReleaseLabel() ) );
 216  
 
 217  20
         if ( releaseDescriptor.isLocalCheckout() && !scmResult.isSuccess() )
 218  
         {
 219  
             // this is not beautiful but needed to indicate that the execute() method
 220  
             // should continue in the parent directory
 221  0
             return null;
 222  
         }
 223  
 
 224  20
         String scmRelativePathProjectDirectory = scmResult.getRelativePathProjectDirectory();
 225  20
         if ( StringUtils.isEmpty( scmRelativePathProjectDirectory ) )
 226  
         {
 227  
             String basedir;
 228  
             try
 229  
             {
 230  20
                 basedir = ReleaseUtil.getCommonBasedir( reactorProjects );
 231  
             }
 232  0
             catch ( IOException e )
 233  
             {
 234  0
                 throw new ReleaseExecutionException( "Exception occurred while calculating common basedir: "
 235  
                     + e.getMessage(), e );
 236  20
             }
 237  
 
 238  20
             String rootProjectBasedir = rootProject.getBasedir().getAbsolutePath();
 239  
             try
 240  
             {
 241  20
                 if ( ReleaseUtil.isSymlink( rootProject.getBasedir() ) )
 242  
                 {
 243  0
                     rootProjectBasedir = rootProject.getBasedir().getCanonicalPath();
 244  
                 }
 245  
             }
 246  0
             catch ( IOException e )
 247  
             {
 248  0
                 throw new ReleaseExecutionException( e.getMessage(), e );
 249  20
             }
 250  20
             if ( rootProjectBasedir.length() > basedir.length() )
 251  
             {
 252  2
                 scmRelativePathProjectDirectory = rootProjectBasedir.substring( basedir.length() + 1 );
 253  
             }
 254  
         }
 255  20
         releaseDescriptor.setScmRelativePathProjectDirectory( scmRelativePathProjectDirectory );
 256  
 
 257  20
         if ( !scmResult.isSuccess() )
 258  
         {
 259  2
             result.setResultCode( ReleaseResult.ERROR );
 260  2
             logError( result, scmResult.getProviderMessage() );
 261  
 
 262  2
             throw new ReleaseScmCommandException( "Unable to checkout from SCM", scmResult );
 263  
         }
 264  
 
 265  18
         result.setResultCode( ReleaseResult.SUCCESS );
 266  
 
 267  18
         return result;
 268  
     }
 269  
 
 270  
     /** {@inheritDoc}  */
 271  
     public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
 272  
                                    List<MavenProject> reactorProjects )
 273  
         throws ReleaseExecutionException, ReleaseFailureException
 274  
     {
 275  2
         ReleaseResult result = new ReleaseResult();
 276  
 
 277  2
         logInfo( result, "The project would be checked out to perform the release ..." );
 278  
 
 279  2
         result.setResultCode( ReleaseResult.SUCCESS );
 280  2
         return result;
 281  
     }
 282  
 }