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.git.repository;
20
21 import java.net.URI;
22 import java.net.URISyntaxException;
23 import java.util.regex.Matcher;
24 import java.util.regex.Pattern;
25
26 import org.apache.maven.scm.ScmException;
27 import org.apache.maven.scm.provider.ScmProviderRepository;
28 import org.apache.maven.scm.provider.ScmProviderRepositoryWithHost;
29
30
31
32
33
34
35 public class GitScmProviderRepository extends ScmProviderRepositoryWithHost {
36
37
38
39
40 public static final String URL_DELIMITER_FETCH = "[fetch=]";
41
42
43
44
45 public static final String URL_DELIMITER_PUSH = "[push=]";
46
47
48
49
50 public static final String PROTOCOL_SEPARATOR = "://";
51
52
53
54
55 public static final String PROTOCOL_FILE = "file";
56
57
58
59
60 public static final String PROTOCOL_GIT = "git";
61
62
63
64
65 public static final String PROTOCOL_SSH = "ssh";
66
67
68
69
70 public static final String PROTOCOL_HTTP = "http";
71
72
73
74
75 public static final String PROTOCOL_HTTPS = "https";
76
77
78
79
80
81 public static final String PROTOCOL_RSYNC = "rsync";
82
83 private static final Pattern HOST_AND_PORT_EXTRACTOR =
84 Pattern.compile("([^:/\\\\~]*)(?::(\\d*))?(?:([:/\\\\~])(.*))?");
85
86
87
88
89
90 public static final String PROTOCOL_NONE = "";
91
92
93
94
95 private String provider;
96
97
98
99
100 private RepositoryUrl fetchInfo;
101
102
103
104
105 private RepositoryUrl pushInfo;
106
107 public GitScmProviderRepository(String url) throws ScmException {
108 if (url == null) {
109 throw new ScmException("url must not be null");
110 }
111
112 if (url.startsWith(URL_DELIMITER_FETCH)) {
113 String fetch = url.substring(URL_DELIMITER_FETCH.length());
114
115 int indexPushDelimiter = fetch.indexOf(URL_DELIMITER_PUSH);
116 if (indexPushDelimiter >= 0) {
117 String push = fetch.substring(indexPushDelimiter + URL_DELIMITER_PUSH.length());
118 pushInfo = parseUrl(push);
119
120 fetch = fetch.substring(0, indexPushDelimiter);
121 }
122
123 fetchInfo = parseUrl(fetch);
124
125 if (pushInfo == null) {
126 pushInfo = fetchInfo;
127 }
128 } else if (url.startsWith(URL_DELIMITER_PUSH)) {
129 String push = url.substring(URL_DELIMITER_PUSH.length());
130
131 int indexFetchDelimiter = push.indexOf(URL_DELIMITER_FETCH);
132 if (indexFetchDelimiter >= 0) {
133 String fetch = push.substring(indexFetchDelimiter + URL_DELIMITER_FETCH.length());
134 fetchInfo = parseUrl(fetch);
135
136 push = push.substring(0, indexFetchDelimiter);
137 }
138
139 pushInfo = parseUrl(push);
140
141 if (fetchInfo == null) {
142 fetchInfo = pushInfo;
143 }
144 } else {
145 fetchInfo = pushInfo = parseUrl(url);
146 }
147
148
149
150 setUser(pushInfo.getUserName());
151 setPassword(pushInfo.getPassword());
152 setHost(pushInfo.getHost());
153 if (pushInfo.getPort() != null && pushInfo.getPort().length() > 0) {
154 setPort(Integer.parseInt(pushInfo.getPort()));
155 }
156 }
157
158 public GitScmProviderRepository(String url, String user, String password) throws ScmException {
159 this(url);
160
161 setUser(user);
162
163 setPassword(password);
164 }
165
166
167
168
169 public String getProvider() {
170 return provider;
171 }
172
173 public RepositoryUrl getFetchInfo() {
174 return fetchInfo;
175 }
176
177 public RepositoryUrl getPushInfo() {
178 return pushInfo;
179 }
180
181
182
183
184 public String getFetchUrl() {
185 return getUrl(fetchInfo);
186 }
187
188
189
190
191 public String getPushUrl() {
192 return getUrl(pushInfo);
193 }
194
195
196
197
198
199
200
201
202
203 private RepositoryUrl parseUrl(String url) throws ScmException {
204 RepositoryUrl repoUrl = new RepositoryUrl();
205
206 url = parseProtocol(repoUrl, url);
207 url = parseUserInfo(repoUrl, url);
208 url = parseHostAndPort(repoUrl, url);
209
210 repoUrl.setPath(url);
211 return repoUrl;
212 }
213
214
215
216
217
218 private String getUrl(RepositoryUrl repoUrl) {
219 StringBuilder urlSb = new StringBuilder(repoUrl.getProtocol());
220 boolean urlSupportsUserInformation = false;
221
222 if (PROTOCOL_SSH.equals(repoUrl.getProtocol())
223 || PROTOCOL_RSYNC.equals(repoUrl.getProtocol())
224 || PROTOCOL_GIT.equals(repoUrl.getProtocol())
225 || PROTOCOL_HTTP.equals(repoUrl.getProtocol())
226 || PROTOCOL_HTTPS.equals(repoUrl.getProtocol())
227 || PROTOCOL_NONE.equals(repoUrl.getProtocol())) {
228 urlSupportsUserInformation = true;
229 }
230
231 if (repoUrl.getProtocol() != null && repoUrl.getProtocol().length() > 0) {
232 urlSb.append("://");
233 }
234
235
236 if (urlSupportsUserInformation) {
237 String userName = repoUrl.getUserName();
238
239 if (getUser() != null && getUser().length() > 0) {
240 userName = getUser();
241 }
242
243 String password = repoUrl.getPassword();
244 if (getPassword() != null && getPassword().length() > 0) {
245 password = getPassword();
246 }
247
248 if (userName != null && userName.length() > 0) {
249 String userInfo = userName;
250 if (password != null && password.length() > 0) {
251 userInfo += ":" + password;
252 }
253
254 try {
255 URI uri = new URI(null, userInfo, "localhost", -1, null, null, null);
256 urlSb.append(uri.getRawUserInfo());
257 } catch (URISyntaxException e) {
258
259
260 e.printStackTrace();
261 }
262
263 urlSb.append('@');
264 }
265 }
266
267
268 urlSb.append(repoUrl.getHost());
269 if (repoUrl.getPort() != null && repoUrl.getPort().length() > 0) {
270 urlSb.append(':').append(repoUrl.getPort());
271 }
272
273
274 urlSb.append(repoUrl.getPath());
275
276 return urlSb.toString();
277 }
278
279
280
281
282
283
284
285
286 private String parseProtocol(RepositoryUrl repoUrl, String url) throws ScmException {
287
288 if (url.startsWith(PROTOCOL_FILE + PROTOCOL_SEPARATOR)) {
289 repoUrl.setProtocol(PROTOCOL_FILE);
290 } else if (url.startsWith(PROTOCOL_HTTPS + PROTOCOL_SEPARATOR)) {
291 repoUrl.setProtocol(PROTOCOL_HTTPS);
292 } else if (url.startsWith(PROTOCOL_HTTP + PROTOCOL_SEPARATOR)) {
293 repoUrl.setProtocol(PROTOCOL_HTTP);
294 } else if (url.startsWith(PROTOCOL_SSH + PROTOCOL_SEPARATOR)) {
295 repoUrl.setProtocol(PROTOCOL_SSH);
296 } else if (url.startsWith(PROTOCOL_GIT + PROTOCOL_SEPARATOR)) {
297 repoUrl.setProtocol(PROTOCOL_GIT);
298 } else if (url.startsWith(PROTOCOL_RSYNC + PROTOCOL_SEPARATOR)) {
299 repoUrl.setProtocol(PROTOCOL_RSYNC);
300 } else {
301
302
303 repoUrl.setProtocol(PROTOCOL_NONE);
304 return url;
305 }
306
307 url = url.substring(repoUrl.getProtocol().length() + 3);
308
309 return url;
310 }
311
312
313
314
315
316
317
318
319
320 private String parseUserInfo(RepositoryUrl repoUrl, String url) throws ScmException {
321 if (PROTOCOL_FILE.equals(repoUrl.getProtocol())) {
322
323 return url;
324 }
325
326 int indexAt = url.lastIndexOf('@');
327 if (indexAt >= 0) {
328 String userInfo = url.substring(0, indexAt);
329 int indexPwdSep = userInfo.indexOf(':');
330 if (indexPwdSep < 0) {
331 repoUrl.setUserName(userInfo);
332 } else {
333 repoUrl.setUserName(userInfo.substring(0, indexPwdSep));
334 repoUrl.setPassword(userInfo.substring(indexPwdSep + 1));
335 }
336
337 url = url.substring(indexAt + 1);
338 }
339 return url;
340 }
341
342
343
344
345
346
347
348
349
350
351 private String parseHostAndPort(RepositoryUrl repoUrl, String url) throws ScmException {
352
353 repoUrl.setPort("");
354 repoUrl.setHost("");
355
356 if (PROTOCOL_FILE.equals(repoUrl.getProtocol())) {
357
358 return url;
359 } else {
360
361 Matcher hostAndPortMatcher = HOST_AND_PORT_EXTRACTOR.matcher(url);
362 if (hostAndPortMatcher.matches()) {
363 if (hostAndPortMatcher.groupCount() > 1 && hostAndPortMatcher.group(1) != null) {
364 repoUrl.setHost(hostAndPortMatcher.group(1));
365 }
366 if (hostAndPortMatcher.groupCount() > 2 && hostAndPortMatcher.group(2) != null) {
367 repoUrl.setPort(hostAndPortMatcher.group(2));
368 }
369
370 StringBuilder computedUrl = new StringBuilder();
371 if (hostAndPortMatcher.group(hostAndPortMatcher.groupCount() - 1) != null) {
372 computedUrl.append(hostAndPortMatcher.group(hostAndPortMatcher.groupCount() - 1));
373 }
374 if (hostAndPortMatcher.group(hostAndPortMatcher.groupCount()) != null) {
375 computedUrl.append(hostAndPortMatcher.group(hostAndPortMatcher.groupCount()));
376 }
377 return computedUrl.toString();
378 } else {
379
380 return url;
381 }
382 }
383 }
384
385
386
387
388 public String getRelativePath(ScmProviderRepository ancestor) {
389 if (ancestor instanceof GitScmProviderRepository) {
390 GitScmProviderRepository gitAncestor = (GitScmProviderRepository) ancestor;
391
392
393 String url = getFetchUrl();
394 String path = url.replaceFirst(gitAncestor.getFetchUrl() + "/", "");
395
396 if (!path.equals(url)) {
397 return path;
398 }
399 }
400 return null;
401 }
402
403
404
405
406 public String toString() {
407
408 if (fetchInfo == pushInfo) {
409 return getUrl(fetchInfo);
410 }
411 return URL_DELIMITER_FETCH + getUrl(fetchInfo) + URL_DELIMITER_PUSH + getUrl(pushInfo);
412 }
413 }