1 package org.apache.maven.scm.provider.svn;
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.util.ArrayList;
24 import java.util.List;
25
26 import org.apache.maven.scm.CommandParameters;
27 import org.apache.maven.scm.ScmException;
28 import org.apache.maven.scm.ScmFileSet;
29 import org.apache.maven.scm.ScmResult;
30 import org.apache.maven.scm.command.add.AddScmResult;
31 import org.apache.maven.scm.command.blame.BlameScmResult;
32 import org.apache.maven.scm.command.branch.BranchScmResult;
33 import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
34 import org.apache.maven.scm.command.checkin.CheckInScmResult;
35 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
36 import org.apache.maven.scm.command.diff.DiffScmResult;
37 import org.apache.maven.scm.command.export.ExportScmResult;
38 import org.apache.maven.scm.command.info.InfoItem;
39 import org.apache.maven.scm.command.info.InfoScmResult;
40 import org.apache.maven.scm.command.list.ListScmResult;
41 import org.apache.maven.scm.command.mkdir.MkdirScmResult;
42 import org.apache.maven.scm.command.remove.RemoveScmResult;
43 import org.apache.maven.scm.command.status.StatusScmResult;
44 import org.apache.maven.scm.command.tag.TagScmResult;
45 import org.apache.maven.scm.command.untag.UntagScmResult;
46 import org.apache.maven.scm.command.update.UpdateScmResult;
47 import org.apache.maven.scm.provider.AbstractScmProvider;
48 import org.apache.maven.scm.provider.ScmProviderRepository;
49 import org.apache.maven.scm.provider.svn.command.SvnCommand;
50 import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
51 import org.apache.maven.scm.provider.svn.util.SvnUtil;
52 import org.apache.maven.scm.repository.ScmRepository;
53 import org.apache.maven.scm.repository.ScmRepositoryException;
54 import org.apache.maven.scm.repository.UnknownRepositoryStructure;
55 import org.codehaus.plexus.util.StringUtils;
56
57
58
59
60
61
62
63 public abstract class AbstractSvnScmProvider
64 extends AbstractScmProvider
65 {
66
67
68
69
70 private static class ScmUrlParserResult
71 {
72 private List<String> messages = new ArrayList<String>();
73
74 private ScmProviderRepository repository;
75 }
76
77 public static final String CURRENT_WORKING_DIRECTORY = "scmCheckWorkingDirectoryUrl.currentWorkingDirectory";
78
79
80
81
82
83
84
85
86 public String getScmSpecificFilename()
87 {
88 return ".svn";
89 }
90
91
92
93
94 public ScmProviderRepository makeProviderScmRepository( String scmSpecificUrl, char delimiter )
95 throws ScmRepositoryException
96 {
97 ScmUrlParserResult result = parseScmUrl( scmSpecificUrl );
98
99 if ( checkCurrentWorkingDirectoryUrl() )
100 {
101 getLogger().debug( "Checking svn info 'URL:' field matches current sources directory" );
102 try
103 {
104 String workingDir = System.getProperty( CURRENT_WORKING_DIRECTORY );
105 InfoScmResult info =
106 info( result.repository, new ScmFileSet( new File( workingDir ) ), new CommandParameters() );
107
108 String url = findUrlInfoItem( info );
109 String comparison = "'" + url + "' vs. '" + scmSpecificUrl + "'";
110 getLogger().debug( "Comparing : " + comparison );
111 if ( url != null && !url.equals( scmSpecificUrl ) )
112 {
113 result.messages.add( "Scm url does not match the value returned by svn info (" + comparison + ")" );
114 }
115 }
116 catch ( ScmException e )
117 {
118 throw new ScmRepositoryException( "An error occurred while trying to svn info", e );
119 }
120 }
121 if ( result.messages.size() > 0 )
122 {
123 throw new ScmRepositoryException( "The scm url is invalid.", result.messages );
124 }
125
126
127 return result.repository;
128 }
129
130 private boolean checkCurrentWorkingDirectoryUrl()
131 {
132 return StringUtils.isNotEmpty( System.getProperty( CURRENT_WORKING_DIRECTORY ) );
133 }
134
135 private String findUrlInfoItem( InfoScmResult infoScmResult )
136 {
137 for ( InfoItem infoItem : infoScmResult.getInfoItems() )
138 {
139 if ( infoItem.getURL() != null )
140 {
141 getLogger().debug( "URL found: " + infoItem.getURL() );
142 return infoItem.getURL();
143 }
144 }
145 getLogger().debug( "URL not found (command output=" + infoScmResult.getCommandOutput() + ")" );
146 return null;
147 }
148
149
150
151
152 public ScmProviderRepository makeProviderScmRepository( File path )
153 throws ScmRepositoryException, UnknownRepositoryStructure
154 {
155 if ( path == null )
156 {
157 throw new NullPointerException( "Path argument is null" );
158 }
159
160 if ( !path.isDirectory() )
161 {
162 throw new ScmRepositoryException( path.getAbsolutePath() + " isn't a valid directory." );
163 }
164
165 if ( !new File( path, ".svn" ).exists() )
166 {
167 throw new ScmRepositoryException( path.getAbsolutePath() + " isn't a svn checkout directory." );
168 }
169
170 try
171 {
172 return makeProviderScmRepository( getRepositoryURL( path ), ':' );
173 }
174 catch ( ScmException e )
175 {
176
177 throw new ScmRepositoryException( "Error executing info command", e );
178 }
179 }
180
181 protected abstract String getRepositoryURL( File path )
182 throws ScmException;
183
184
185
186
187 public List<String> validateScmUrl( String scmSpecificUrl, char delimiter )
188 {
189 List<String> messages = new ArrayList<String>();
190 try
191 {
192 makeProviderScmRepository( scmSpecificUrl, delimiter );
193 }
194 catch ( ScmRepositoryException e )
195 {
196 messages = e.getValidationMessages();
197 }
198 return messages;
199 }
200
201
202
203
204 public String getScmType()
205 {
206 return "svn";
207 }
208
209
210
211
212
213 private ScmUrlParserResult parseScmUrl( String scmSpecificUrl )
214 {
215 ScmUrlParserResult result = new ScmUrlParserResult();
216
217 String url = scmSpecificUrl;
218
219
220
221
222
223 if ( url.startsWith( "file" ) )
224 {
225 if ( !url.startsWith( "file://" ) )
226 {
227 result.messages.add( "A svn 'file' url must be on the form 'file://[hostname]/'." );
228
229 return result;
230 }
231 }
232 else if ( url.startsWith( "https" ) )
233 {
234 if ( !url.startsWith( "https://" ) )
235 {
236 result.messages.add( "A svn 'http' url must be on the form 'https://'." );
237
238 return result;
239 }
240 }
241 else if ( url.startsWith( "http" ) )
242 {
243 if ( !url.startsWith( "http://" ) )
244 {
245 result.messages.add( "A svn 'http' url must be on the form 'http://'." );
246
247 return result;
248 }
249 }
250
251 else if ( url.startsWith( "svn+" ) )
252 {
253 if ( url.indexOf( "://" ) < 0 )
254 {
255 result.messages.add( "A svn 'svn+xxx' url must be on the form 'svn+xxx://'." );
256
257 return result;
258 }
259 else
260 {
261 String tunnel = url.substring( "svn+".length(), url.indexOf( "://" ) );
262
263
264 if ( !"ssh".equals( tunnel ) )
265 {
266 SvnConfigFileReader reader = new SvnConfigFileReader();
267 if ( SvnUtil.getSettings().getConfigDirectory() != null )
268 {
269 reader.setConfigDirectory( new File( SvnUtil.getSettings().getConfigDirectory() ) );
270 }
271
272 if ( StringUtils.isEmpty( reader.getProperty( "tunnels", tunnel ) ) )
273 {
274 result.messages.add(
275 "The tunnel '" + tunnel + "' isn't defined in your subversion configuration file." );
276
277 return result;
278 }
279 }
280 }
281 }
282 else if ( url.startsWith( "svn" ) )
283 {
284 if ( !url.startsWith( "svn://" ) )
285 {
286 result.messages.add( "A svn 'svn' url must be on the form 'svn://'." );
287
288 return result;
289 }
290 }
291 else
292 {
293 result.messages.add( url + " url isn't a valid svn URL." );
294
295 return result;
296 }
297
298 result.repository = new SvnScmProviderRepository( url );
299
300 return result;
301 }
302
303 protected abstract SvnCommand getAddCommand();
304
305
306
307
308 public AddScmResult add( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
309 throws ScmException
310 {
311 return (AddScmResult) executeCommand( getAddCommand(), repository, fileSet, parameters );
312 }
313
314 protected abstract SvnCommand getBranchCommand();
315
316
317
318
319 protected BranchScmResult branch( ScmProviderRepository repository, ScmFileSet fileSet,
320 CommandParameters parameters )
321 throws ScmException
322 {
323 return (BranchScmResult) executeCommand( getBranchCommand(), repository, fileSet, parameters );
324 }
325
326 protected abstract SvnCommand getChangeLogCommand();
327
328
329
330
331 public ChangeLogScmResult changelog( ScmProviderRepository repository, ScmFileSet fileSet,
332 CommandParameters parameters )
333 throws ScmException
334 {
335 return (ChangeLogScmResult) executeCommand( getChangeLogCommand(), repository, fileSet, parameters );
336 }
337
338 protected abstract SvnCommand getCheckInCommand();
339
340
341
342
343 public CheckInScmResult checkin( ScmProviderRepository repository, ScmFileSet fileSet,
344 CommandParameters parameters )
345 throws ScmException
346 {
347 return (CheckInScmResult) executeCommand( getCheckInCommand(), repository, fileSet, parameters );
348 }
349
350 protected abstract SvnCommand getCheckOutCommand();
351
352
353
354
355 public CheckOutScmResult checkout( ScmProviderRepository repository, ScmFileSet fileSet,
356 CommandParameters parameters )
357 throws ScmException
358 {
359 return (CheckOutScmResult) executeCommand( getCheckOutCommand(), repository, fileSet, parameters );
360 }
361
362 protected abstract SvnCommand getDiffCommand();
363
364
365
366
367 public DiffScmResult diff( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
368 throws ScmException
369 {
370 return (DiffScmResult) executeCommand( getDiffCommand(), repository, fileSet, parameters );
371 }
372
373 protected abstract SvnCommand getExportCommand();
374
375
376
377
378 protected ExportScmResult export( ScmProviderRepository repository, ScmFileSet fileSet,
379 CommandParameters parameters )
380 throws ScmException
381 {
382 return (ExportScmResult) executeCommand( getExportCommand(), repository, fileSet, parameters );
383 }
384
385 protected abstract SvnCommand getRemoveCommand();
386
387
388
389
390 public RemoveScmResult remove( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
391 throws ScmException
392 {
393 return (RemoveScmResult) executeCommand( getRemoveCommand(), repository, fileSet, parameters );
394 }
395
396 protected abstract SvnCommand getStatusCommand();
397
398
399
400
401 public StatusScmResult status( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
402 throws ScmException
403 {
404 return (StatusScmResult) executeCommand( getStatusCommand(), repository, fileSet, parameters );
405 }
406
407 protected abstract SvnCommand getTagCommand();
408
409
410
411
412 public TagScmResult tag( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
413 throws ScmException
414 {
415 return (TagScmResult) executeCommand( getTagCommand(), repository, fileSet, parameters );
416 }
417
418 protected abstract SvnCommand getUntagCommand();
419
420
421
422
423 @Override
424 public UntagScmResult untag( ScmRepository repository, ScmFileSet fileSet, CommandParameters parameters )
425 throws ScmException
426 {
427 return (UntagScmResult) executeCommand( getUntagCommand(), repository.getProviderRepository(),
428 fileSet, parameters );
429 }
430
431 protected abstract SvnCommand getUpdateCommand();
432
433
434
435
436 public UpdateScmResult update( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
437 throws ScmException
438 {
439 return (UpdateScmResult) executeCommand( getUpdateCommand(), repository, fileSet, parameters );
440 }
441
442 protected ScmResult executeCommand( SvnCommand command, ScmProviderRepository repository, ScmFileSet fileSet,
443 CommandParameters parameters )
444 throws ScmException
445 {
446 command.setLogger( getLogger() );
447
448 return command.execute( repository, fileSet, parameters );
449 }
450
451 protected abstract SvnCommand getListCommand();
452
453
454
455
456 public ListScmResult list( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
457 throws ScmException
458 {
459 SvnCommand cmd = getListCommand();
460
461 return (ListScmResult) executeCommand( cmd, repository, fileSet, parameters );
462 }
463
464 protected abstract SvnCommand getInfoCommand();
465
466 public InfoScmResult info( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
467 throws ScmException
468 {
469 SvnCommand cmd = getInfoCommand();
470
471 return (InfoScmResult) executeCommand( cmd, repository, fileSet, parameters );
472 }
473
474
475
476
477 protected BlameScmResult blame( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
478 throws ScmException
479 {
480 SvnCommand cmd = getBlameCommand();
481
482 return (BlameScmResult) executeCommand( cmd, repository, fileSet, parameters );
483 }
484
485 protected abstract SvnCommand getBlameCommand();
486
487
488
489
490 public MkdirScmResult mkdir( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
491 throws ScmException
492 {
493 SvnCommand cmd = getMkdirCommand();
494
495 return (MkdirScmResult) executeCommand( cmd, repository, fileSet, parameters );
496 }
497
498 protected abstract SvnCommand getMkdirCommand();
499
500
501
502
503
504
505
506
507 public abstract boolean remoteUrlExist( ScmProviderRepository repository, CommandParameters parameters )
508 throws ScmException;
509 }