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.nio.file.LinkOption;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.util.List;
28
29 import org.apache.maven.project.MavenProject;
30 import org.apache.maven.scm.CommandParameter;
31 import org.apache.maven.scm.CommandParameters;
32 import org.apache.maven.scm.ScmException;
33 import org.apache.maven.scm.ScmFileSet;
34 import org.apache.maven.scm.ScmTag;
35 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
36 import org.apache.maven.scm.manager.NoSuchScmProviderException;
37 import org.apache.maven.scm.provider.ScmProvider;
38 import org.apache.maven.scm.repository.ScmRepository;
39 import org.apache.maven.scm.repository.ScmRepositoryException;
40 import org.apache.maven.shared.release.ReleaseExecutionException;
41 import org.apache.maven.shared.release.ReleaseFailureException;
42 import org.apache.maven.shared.release.ReleaseResult;
43 import org.apache.maven.shared.release.config.ReleaseDescriptor;
44 import org.apache.maven.shared.release.env.ReleaseEnvironment;
45 import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
46 import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
47 import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
48 import org.apache.maven.shared.release.util.ReleaseUtil;
49 import org.codehaus.plexus.component.annotations.Component;
50 import org.codehaus.plexus.component.annotations.Requirement;
51 import org.codehaus.plexus.util.FileUtils;
52 import org.codehaus.plexus.util.StringUtils;
53
54
55
56
57 @Component( role = ReleasePhase.class, hint = "checkout-project-from-scm" )
58 public class CheckoutProjectFromScm
59 extends AbstractReleasePhase
60 {
61
62
63
64 @Requirement
65 private ScmRepositoryConfigurator scmRepositoryConfigurator;
66
67 @Override
68 public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
69 List<MavenProject> reactorProjects )
70 throws ReleaseExecutionException, ReleaseFailureException
71 {
72 ReleaseResult releaseResult = null;
73
74 if ( releaseDescriptor.isLocalCheckout() )
75 {
76
77
78
79
80
81 String providerPart = releaseDescriptor.getScmSourceUrl()
82 .substring( 0, releaseDescriptor.getScmSourceUrl().indexOf( ':', 4 ) );
83
84 String scmPath = releaseDescriptor.getWorkingDirectory();
85
86
87
88
89 do
90 {
91 try
92 {
93 if ( scmPath.startsWith( "/" ) )
94 {
95
96 scmPath = scmPath.substring( 1 );
97 }
98
99 String scmUrl = providerPart + ":file:///" + scmPath;
100 releaseDescriptor.setScmSourceUrl( scmUrl );
101 getLogger().info( "Performing a LOCAL checkout from " + releaseDescriptor.getScmSourceUrl() );
102
103 releaseResult = performCheckout( releaseDescriptor, releaseEnvironment, reactorProjects );
104 }
105 catch ( ScmException scmEx )
106 {
107
108 releaseResult = null;
109 }
110
111 if ( releaseResult == null || releaseResult.getResultCode() == ReleaseResult.ERROR )
112 {
113
114
115 releaseResult = null;
116
117
118 int lastSlashPos = scmPath.lastIndexOf( File.separator );
119 if ( lastSlashPos > 0 )
120 {
121 scmPath = scmPath.substring( 0, lastSlashPos );
122 }
123 else
124 {
125 throw new ReleaseExecutionException( "could not perform a local checkout" );
126 }
127 }
128 }
129 while ( releaseResult == null );
130 }
131 else
132 {
133
134 try
135 {
136 releaseResult = performCheckout( releaseDescriptor, releaseEnvironment, reactorProjects );
137 }
138 catch ( ScmException e )
139 {
140 releaseResult = new ReleaseResult();
141 releaseResult.setResultCode( ReleaseResult.ERROR );
142 logError( releaseResult, e.getMessage() );
143
144 throw new ReleaseExecutionException( "An error is occurred in the checkout process: "
145 + e.getMessage(), e );
146 }
147
148 }
149
150 return releaseResult;
151 }
152
153
154 private ReleaseResult performCheckout( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
155 List<MavenProject> reactorProjects )
156 throws ReleaseExecutionException, ReleaseFailureException, ScmException
157 {
158 ReleaseResult result = new ReleaseResult();
159
160 logInfo( result, "Checking out the project to perform the release ..." );
161
162 ScmRepository repository;
163 ScmProvider provider;
164
165 try
166 {
167 repository = scmRepositoryConfigurator.getConfiguredRepository( releaseDescriptor,
168 releaseEnvironment.getSettings() );
169
170 provider = scmRepositoryConfigurator.getRepositoryProvider( repository );
171 }
172 catch ( ScmRepositoryException e )
173 {
174 result.setResultCode( ReleaseResult.ERROR );
175 logError( result, e.getMessage() );
176
177 throw new ReleaseScmRepositoryException( e.getMessage(), e.getValidationMessages() );
178 }
179 catch ( NoSuchScmProviderException e )
180 {
181 result.setResultCode( ReleaseResult.ERROR );
182 logError( result, e.getMessage() );
183
184 throw new ReleaseExecutionException( "Unable to configure SCM repository: " + e.getMessage(), e );
185 }
186
187 MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
188
189
190 File checkoutDirectory =
191 FileUtils.resolveFile( rootProject.getBasedir(), releaseDescriptor.getCheckoutDirectory() );
192
193 if ( checkoutDirectory.exists() )
194 {
195 try
196 {
197 FileUtils.deleteDirectory( checkoutDirectory );
198 }
199 catch ( IOException e )
200 {
201 result.setResultCode( ReleaseResult.ERROR );
202 logError( result, e.getMessage() );
203
204 throw new ReleaseExecutionException( "Unable to remove old checkout directory: " + e.getMessage(), e );
205 }
206 }
207
208 checkoutDirectory.mkdirs();
209
210 CommandParameters commandParameters = new CommandParameters();
211 commandParameters.setString( CommandParameter.SHALLOW, Boolean.TRUE.toString() );
212
213 CheckOutScmResult scmResult = provider.checkOut( repository, new ScmFileSet( checkoutDirectory ),
214 new ScmTag( releaseDescriptor.getScmReleaseLabel() ), commandParameters );
215
216 if ( releaseDescriptor.isLocalCheckout() && !scmResult.isSuccess() )
217 {
218
219
220 return null;
221 }
222
223 String scmRelativePathProjectDirectory = scmResult.getRelativePathProjectDirectory();
224 if ( StringUtils.isEmpty( scmRelativePathProjectDirectory ) )
225 {
226 Path workingDirectory = Paths.get( releaseDescriptor.getWorkingDirectory() );
227
228 Path rootProjectBasedir;
229 try
230 {
231 rootProjectBasedir = rootProject.getBasedir().toPath().toRealPath( LinkOption.NOFOLLOW_LINKS );
232 }
233 catch ( IOException e )
234 {
235 throw new ReleaseExecutionException( e.getMessage(), e );
236 }
237
238 scmRelativePathProjectDirectory = workingDirectory.relativize( rootProjectBasedir ).toString();
239 }
240 releaseDescriptor.setScmRelativePathProjectDirectory( scmRelativePathProjectDirectory );
241
242 if ( !scmResult.isSuccess() )
243 {
244 result.setResultCode( ReleaseResult.ERROR );
245 logError( result, scmResult.getProviderMessage() );
246
247 throw new ReleaseScmCommandException( "Unable to checkout from SCM", scmResult );
248 }
249
250 result.setResultCode( ReleaseResult.SUCCESS );
251
252 return result;
253 }
254
255 @Override
256 public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
257 List<MavenProject> reactorProjects )
258 throws ReleaseExecutionException, ReleaseFailureException
259 {
260 ReleaseResult result = new ReleaseResult();
261
262 if ( releaseDescriptor.isLocalCheckout() )
263 {
264 logInfo( result, "This would be a LOCAL check out to perform the release ..." );
265 }
266 else
267 {
268 logInfo( result, "The project would be checked out to perform the release ..." );
269 }
270
271 result.setResultCode( ReleaseResult.SUCCESS );
272 return result;
273 }
274 }