View Javadoc

1   package org.apache.continuum.scm;
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 org.apache.commons.io.FileUtils;
23  import org.apache.commons.lang.StringUtils;
24  import org.apache.maven.scm.ScmException;
25  import org.apache.maven.scm.ScmFileSet;
26  import org.apache.maven.scm.ScmTag;
27  import org.apache.maven.scm.ScmVersion;
28  import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
29  import org.apache.maven.scm.command.checkout.CheckOutScmResult;
30  import org.apache.maven.scm.command.update.UpdateScmResult;
31  import org.apache.maven.scm.manager.NoSuchScmProviderException;
32  import org.apache.maven.scm.manager.ScmManager;
33  import org.apache.maven.scm.repository.ScmRepository;
34  import org.apache.maven.scm.repository.ScmRepositoryException;
35  import org.springframework.stereotype.Service;
36  
37  import java.io.File;
38  import java.io.IOException;
39  import java.util.Calendar;
40  import java.util.Date;
41  import javax.annotation.Resource;
42  
43  /**
44   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
45   * @version $Id: DefaultContinuumScm.java 1372260 2012-08-13 04:29:09Z brett $
46   * @todo consider folding some of this into Maven SCM itself
47   */
48  @Service( "continuumScm" )
49  public class DefaultContinuumScm
50      implements ContinuumScm
51  {
52      /**
53       * The Maven SCM manager to use.
54       */
55      @Resource
56      private ScmManager scmManager;
57  
58      public CheckOutScmResult checkout( ContinuumScmConfiguration configuration )
59          throws IOException, ScmException
60      {
61          ScmVersion scmVersion = getScmVersion( configuration );
62  
63          // TODO: probably need to base this from a working directory in the main configuration
64          File workingDirectory = configuration.getWorkingDirectory();
65  
66          ScmRepository repository = getScmRepository( configuration );
67  
68          CheckOutScmResult result;
69  
70          // TODO: synchronizing *all* checkouts is unnecessary
71          synchronized ( this )
72          {
73              if ( !workingDirectory.exists() )
74              {
75                  if ( !workingDirectory.mkdirs() )
76                  {
77                      throw new IOException( "Could not make directory: " + workingDirectory.getAbsolutePath() );
78                  }
79              }
80              else
81              {
82                  FileUtils.cleanDirectory( workingDirectory );
83              }
84  
85              ScmFileSet fileSet = new ScmFileSet( workingDirectory );
86  
87              result = scmManager.checkOut( repository, fileSet, scmVersion );
88          }
89          return result;
90      }
91  
92      private ScmVersion getScmVersion( ContinuumScmConfiguration configuration )
93      {
94          String tag = configuration.getTag();
95  
96          ScmVersion scmVersion = null;
97          if ( tag != null )
98          {
99              // TODO: differentiate between tag and branch? Allow for revision?
100             scmVersion = new ScmTag( tag );
101         }
102         return scmVersion;
103     }
104 
105     public UpdateScmResult update( ContinuumScmConfiguration configuration )
106         throws ScmException
107     {
108         ScmVersion scmVersion = getScmVersion( configuration );
109 
110         File workingDirectory = configuration.getWorkingDirectory();
111         if ( !workingDirectory.exists() )
112         {
113             // TODO: maybe we could check it out - it seems we currently rely on Continuum figuring this out
114             throw new IllegalStateException(
115                 "The working directory for the project doesn't exist " + "(" + workingDirectory.getAbsolutePath() +
116                     ")." );
117         }
118 
119         ScmRepository repository = getScmRepository( configuration );
120 
121         // Some SCM provider requires additional system properties during update
122         if ( "starteam".equals( repository.getProvider() ) )
123         {
124             // TODO: remove the use of system property - need a better way to pass provider specific configuration
125 
126             // Remove the clientspec name, so it will be recalculated between each command for each project
127             // instead of use the same for all projects
128             System.setProperty( "maven.scm.starteam.deleteLocal", "true" );
129         }
130 
131         UpdateScmResult result;
132 
133         ScmFileSet fileSet = new ScmFileSet( workingDirectory );
134 
135         // TODO: shouldn't need to synchronize this
136         synchronized ( this )
137         {
138             result = scmManager.update( repository, fileSet, scmVersion, configuration.getLatestUpdateDate() );
139         }
140 
141         return result;
142     }
143 
144     public ChangeLogScmResult changeLog( ContinuumScmConfiguration configuration )
145         throws ScmException
146     {
147         ScmVersion scmVersion = getScmVersion( configuration );
148         Date startDate = null;
149 
150         // TODO: probably need to base this from a working directory in the main configuration
151         File workingDirectory = configuration.getWorkingDirectory();
152 
153         ScmRepository repository = getScmRepository( configuration );
154 
155         ChangeLogScmResult result;
156 
157         ScmFileSet fileSet = new ScmFileSet( workingDirectory );
158 
159         if ( scmVersion == null || StringUtils.isBlank( scmVersion.getName() ) )
160         {
161             // let's get the start date instead
162             startDate = getScmStartDate( configuration );
163 
164             result = scmManager.changeLog( repository, fileSet, startDate, null, 0, null, null );
165         }
166         else
167         {
168             result = scmManager.changeLog( repository, fileSet, scmVersion, scmVersion );
169         }
170 
171         return result;
172     }
173 
174     /**
175      * Create a Maven SCM repository for obtaining the checkout from.
176      *
177      * @param configuration the configuration for the working copy and SCM
178      * @return the repository created
179      * @throws NoSuchScmProviderException
180      * @throws ScmRepositoryException
181      */
182     private ScmRepository getScmRepository( ContinuumScmConfiguration configuration )
183         throws ScmRepositoryException, NoSuchScmProviderException
184     {
185         ScmRepository repository = scmManager.makeScmRepository( configuration.getUrl() );
186 
187         // TODO: tie together with the clientspec change below
188         // This checkout will be retained between uses, so it remains connected to the repository
189         repository.getProviderRepository().setPersistCheckout( true );
190 
191         // TODO: should this be svnexe?
192         if ( !configuration.isUseCredentialsCache() || !"svn".equals( repository.getProvider() ) )
193         {
194             if ( !StringUtils.isEmpty( configuration.getUsername() ) )
195             {
196                 repository.getProviderRepository().setUser( configuration.getUsername() );
197 
198                 if ( !StringUtils.isEmpty( configuration.getPassword() ) )
199                 {
200                     repository.getProviderRepository().setPassword( configuration.getPassword() );
201                 }
202                 else
203                 {
204                     repository.getProviderRepository().setPassword( "" );
205                 }
206             }
207         }
208 
209         if ( "perforce".equals( repository.getProvider() ) )
210         {
211             // TODO: remove the use of system property - need a better way to pass provider specific configuration
212 
213             // Remove the clientspec name, so it will be recalculated between each command for each project
214             // instead of use the same for all projects
215             System.setProperty( "maven.scm.perforce.clientspec.name", "" );
216         }
217 
218         return repository;
219     }
220 
221     private Date getScmStartDate( ContinuumScmConfiguration configuration )
222     {
223         Date startDate = configuration.getLatestUpdateDate();
224 
225         if ( startDate == null )
226         {
227             // start date defaults to January 1, 1970
228             Calendar cal = Calendar.getInstance();
229             cal.set( 1970, Calendar.JANUARY, 1 );
230             startDate = cal.getTime();
231         }
232 
233         return startDate;
234     }
235 
236     public ScmManager getScmManager()
237     {
238         return scmManager;
239     }
240 
241     public void setScmManager( ScmManager scmManager )
242     {
243         this.scmManager = scmManager;
244     }
245 
246     // TODO: add a nuke() method
247 }