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