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