1 package org.apache.maven.shared.release.phase;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
49
50
51
52 public class CheckoutProjectFromScm
53 extends AbstractReleasePhase
54 {
55
56
57
58
59
60 private ScmRepositoryConfigurator scmRepositoryConfigurator;
61
62
63 public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
64 List<MavenProject> reactorProjects )
65 throws ReleaseExecutionException, ReleaseFailureException
66 {
67 ReleaseResult releaseResult = null;
68
69 if ( releaseDescriptor.isLocalCheckout() )
70 {
71
72
73
74
75
76 String providerPart = releaseDescriptor.getScmSourceUrl()
77 .substring( 0, releaseDescriptor.getScmSourceUrl().indexOf( ':', 4 ) );
78
79 String scmPath = releaseDescriptor.getWorkingDirectory();
80
81
82
83
84 do
85 {
86 try
87 {
88 if ( scmPath.startsWith( "/" ) )
89 {
90
91 scmPath = scmPath.substring( 1 );
92 }
93
94 String scmUrl = providerPart + ":file:///" + scmPath;
95 releaseDescriptor.setScmSourceUrl( scmUrl );
96 getLogger().info( "Performing a LOCAL checkout from " + releaseDescriptor.getScmSourceUrl() );
97
98 releaseResult = performCheckout( releaseDescriptor, releaseEnvironment, reactorProjects );
99 }
100 catch ( ScmException scmEx )
101 {
102
103 releaseResult = null;
104 }
105
106 if ( releaseResult == null || releaseResult.getResultCode() == ReleaseResult.ERROR )
107 {
108
109
110 releaseResult = null;
111
112
113 int lastSlashPos = scmPath.lastIndexOf( File.separator );
114 if ( lastSlashPos > 0 )
115 {
116 scmPath = scmPath.substring( 0, lastSlashPos );
117 }
118 else
119 {
120 throw new ReleaseExecutionException( "could not perform a local checkout" );
121 }
122 }
123 }
124 while ( releaseResult == null );
125 }
126 else
127 {
128
129 try
130 {
131 releaseResult = performCheckout( releaseDescriptor, releaseEnvironment, reactorProjects );
132 }
133 catch ( ScmException e )
134 {
135 releaseResult = new ReleaseResult();
136 releaseResult.setResultCode( ReleaseResult.ERROR );
137 logError( releaseResult, e.getMessage() );
138
139 throw new ReleaseExecutionException( "An error is occurred in the checkout process: "
140 + e.getMessage(), e );
141 }
142
143 }
144
145 return releaseResult;
146 }
147
148
149 private ReleaseResult performCheckout( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
150 List<MavenProject> reactorProjects )
151 throws ReleaseExecutionException, ReleaseFailureException, ScmException
152 {
153 ReleaseResult result = new ReleaseResult();
154
155 logInfo( result, "Checking out the project to perform the release ..." );
156
157 ScmRepository repository;
158 ScmProvider provider;
159
160 try
161 {
162 repository = scmRepositoryConfigurator.getConfiguredRepository( releaseDescriptor,
163 releaseEnvironment.getSettings() );
164
165 provider = scmRepositoryConfigurator.getRepositoryProvider( repository );
166 }
167 catch ( ScmRepositoryException e )
168 {
169 result.setResultCode( ReleaseResult.ERROR );
170 logError( result, e.getMessage() );
171
172 throw new ReleaseScmRepositoryException( e.getMessage(), e.getValidationMessages() );
173 }
174 catch ( NoSuchScmProviderException e )
175 {
176 result.setResultCode( ReleaseResult.ERROR );
177 logError( result, e.getMessage() );
178
179 throw new ReleaseExecutionException( "Unable to configure SCM repository: " + e.getMessage(), e );
180 }
181
182 MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
183
184 File checkoutDirectory;
185 if ( StringUtils.isEmpty( releaseDescriptor.getCheckoutDirectory() ) )
186 {
187 checkoutDirectory = new File( rootProject.getFile().getParentFile(), "target/checkout" );
188 releaseDescriptor.setCheckoutDirectory( checkoutDirectory.getAbsolutePath() );
189 }
190 else
191 {
192 checkoutDirectory = new File( releaseDescriptor.getCheckoutDirectory() );
193 }
194
195 if ( checkoutDirectory.exists() )
196 {
197 try
198 {
199 FileUtils.deleteDirectory( checkoutDirectory );
200 }
201 catch ( IOException e )
202 {
203 result.setResultCode( ReleaseResult.ERROR );
204 logError( result, e.getMessage() );
205
206 throw new ReleaseExecutionException( "Unable to remove old checkout directory: " + e.getMessage(), e );
207 }
208 }
209
210 checkoutDirectory.mkdirs();
211
212 CheckOutScmResult scmResult;
213
214 scmResult = provider.checkOut( repository, new ScmFileSet( checkoutDirectory ),
215 new ScmTag( releaseDescriptor.getScmReleaseLabel() ) );
216
217 if ( releaseDescriptor.isLocalCheckout() && !scmResult.isSuccess() )
218 {
219
220
221 return null;
222 }
223
224 String scmRelativePathProjectDirectory = scmResult.getRelativePathProjectDirectory();
225 if ( StringUtils.isEmpty( scmRelativePathProjectDirectory ) )
226 {
227 String basedir;
228 try
229 {
230 basedir = ReleaseUtil.getCommonBasedir( reactorProjects );
231 }
232 catch ( IOException e )
233 {
234 throw new ReleaseExecutionException( "Exception occurred while calculating common basedir: "
235 + e.getMessage(), e );
236 }
237
238 String rootProjectBasedir = rootProject.getBasedir().getAbsolutePath();
239 try
240 {
241 if ( ReleaseUtil.isSymlink( rootProject.getBasedir() ) )
242 {
243 rootProjectBasedir = rootProject.getBasedir().getCanonicalPath();
244 }
245 }
246 catch ( IOException e )
247 {
248 throw new ReleaseExecutionException( e.getMessage(), e );
249 }
250 if ( rootProjectBasedir.length() > basedir.length() )
251 {
252 scmRelativePathProjectDirectory = rootProjectBasedir.substring( basedir.length() + 1 );
253 }
254 }
255 releaseDescriptor.setScmRelativePathProjectDirectory( scmRelativePathProjectDirectory );
256
257 if ( !scmResult.isSuccess() )
258 {
259 result.setResultCode( ReleaseResult.ERROR );
260 logError( result, scmResult.getProviderMessage() );
261
262 throw new ReleaseScmCommandException( "Unable to checkout from SCM", scmResult );
263 }
264
265 result.setResultCode( ReleaseResult.SUCCESS );
266
267 return result;
268 }
269
270
271 public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
272 List<MavenProject> reactorProjects )
273 throws ReleaseExecutionException, ReleaseFailureException
274 {
275 ReleaseResult result = new ReleaseResult();
276
277 if ( releaseDescriptor.isLocalCheckout() )
278 {
279 logInfo( result, "This would be a LOCAL check out to perform the release ..." );
280 }
281 else
282 {
283 logInfo( result, "The project would be checked out to perform the release ..." );
284 }
285
286 result.setResultCode( ReleaseResult.SUCCESS );
287 return result;
288 }
289 }