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