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