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