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() ) || PROTOCOL_RSYNC.equals( repoUrl.getProtocol() )
252 || PROTOCOL_GIT.equals( repoUrl.getProtocol() ) || PROTOCOL_HTTP.equals( repoUrl.getProtocol() )
253 || PROTOCOL_HTTPS.equals( repoUrl.getProtocol() ) || PROTOCOL_NONE.equals( repoUrl.getProtocol() ) )
254 {
255 urlSupportsUserInformation = true;
256 }
257
258 if ( repoUrl.getProtocol() != null && repoUrl.getProtocol().length() > 0 )
259 {
260 urlSb.append( "://" );
261 }
262
263
264 if ( urlSupportsUserInformation )
265 {
266 String userName = repoUrl.getUserName();
267
268 if ( getUser() != null && getUser().length() > 0 )
269 {
270 userName = getUser();
271 }
272
273 String password = repoUrl.getPassword();
274 if ( getPassword() != null && getPassword().length() > 0 )
275 {
276 password = getPassword();
277 }
278
279 if ( userName != null && userName.length() > 0 )
280 {
281 try
282 {
283 urlSb.append( URLEncoder.encode( userName, "UTF-8" ) );
284 }
285 catch ( UnsupportedEncodingException e )
286 {
287
288
289 e.printStackTrace();
290 }
291
292 if ( password != null && password.length() > 0 )
293 {
294 urlSb.append( ':' );
295 try
296 {
297 urlSb.append( URLEncoder.encode( password, "UTF-8" ) );
298 }
299 catch ( UnsupportedEncodingException e )
300 {
301
302
303 e.printStackTrace();
304 }
305 }
306
307 urlSb.append( '@' );
308 }
309 }
310
311
312 urlSb.append( repoUrl.getHost() );
313 if ( repoUrl.getPort() != null && repoUrl.getPort().length() > 0 )
314 {
315 urlSb.append( ':' ).append( repoUrl.getPort() );
316 }
317
318
319 urlSb.append( repoUrl.getPath() );
320
321 return urlSb.toString();
322 }
323
324
325
326
327
328
329
330
331 private String parseProtocol( RepositoryUrl repoUrl, String url )
332 throws ScmException
333 {
334
335 if ( url.startsWith( PROTOCOL_FILE + PROTOCOL_SEPARATOR ) )
336 {
337 repoUrl.setProtocol( PROTOCOL_FILE );
338 }
339 else if ( url.startsWith( PROTOCOL_HTTPS + PROTOCOL_SEPARATOR ) )
340 {
341 repoUrl.setProtocol( PROTOCOL_HTTPS );
342 }
343 else if ( url.startsWith( PROTOCOL_HTTP + PROTOCOL_SEPARATOR ) )
344 {
345 repoUrl.setProtocol( PROTOCOL_HTTP );
346 }
347 else if ( url.startsWith( PROTOCOL_SSH + PROTOCOL_SEPARATOR ) )
348 {
349 repoUrl.setProtocol( PROTOCOL_SSH );
350 }
351 else if ( url.startsWith( PROTOCOL_GIT + PROTOCOL_SEPARATOR ) )
352 {
353 repoUrl.setProtocol( PROTOCOL_GIT );
354 }
355 else if ( url.startsWith( PROTOCOL_RSYNC + PROTOCOL_SEPARATOR ) )
356 {
357 repoUrl.setProtocol( PROTOCOL_RSYNC );
358 }
359 else
360 {
361
362
363 repoUrl.setProtocol( PROTOCOL_NONE );
364 return url;
365 }
366
367 url = url.substring( repoUrl.getProtocol().length() + 3 );
368
369 return url;
370 }
371
372
373
374
375
376
377
378
379
380 private String parseUserInfo( RepositoryUrl repoUrl, String url )
381 throws ScmException
382 {
383
384 int indexAt = url.indexOf( '@' );
385 if ( indexAt >= 0 )
386 {
387 String userInfo = url.substring( 0, indexAt );
388 int indexPwdSep = userInfo.indexOf( ':' );
389 if ( indexPwdSep < 0 )
390 {
391 repoUrl.setUserName( userInfo );
392 }
393 else
394 {
395 repoUrl.setUserName( userInfo.substring( 0, indexPwdSep ) );
396 repoUrl.setPassword( userInfo.substring( indexPwdSep + 1 ) );
397 }
398
399 url = url.substring( indexAt + 1 );
400 }
401 return url;
402 }
403
404
405
406
407
408
409
410
411
412
413 private String parseHostAndPort( RepositoryUrl repoUrl, String url )
414 throws ScmException
415 {
416
417 repoUrl.setPort( "" );
418 repoUrl.setHost( "" );
419
420 if ( PROTOCOL_FILE.equals( repoUrl.getProtocol() ) )
421 {
422
423 return url;
424 }
425 else
426 {
427
428 Matcher hostAndPortMatcher = HOST_AND_PORT_EXTRACTOR.matcher( url );
429 if ( hostAndPortMatcher.matches() )
430 {
431 if ( hostAndPortMatcher.groupCount() > 1 && hostAndPortMatcher.group( 1 ) != null )
432 {
433 repoUrl.setHost( hostAndPortMatcher.group( 1 ) );
434 }
435 if ( hostAndPortMatcher.groupCount() > 2 && hostAndPortMatcher.group( 2 ) != null )
436 {
437 repoUrl.setPort( hostAndPortMatcher.group( 2 ) );
438 }
439
440 StringBuilder computedUrl = new StringBuilder();
441 if ( hostAndPortMatcher.group( hostAndPortMatcher.groupCount() - 1 ) != null )
442 {
443 computedUrl.append( hostAndPortMatcher.group( hostAndPortMatcher.groupCount() - 1 ) );
444 }
445 if ( hostAndPortMatcher.group( hostAndPortMatcher.groupCount() ) != null )
446 {
447 computedUrl.append( hostAndPortMatcher.group( hostAndPortMatcher.groupCount() ) );
448 }
449 return computedUrl.toString();
450 }
451 else
452 {
453
454 return url;
455 }
456 }
457 }
458
459
460
461
462
463 public String getRelativePath( ScmProviderRepository ancestor )
464 {
465 if ( ancestor instanceof GitScmProviderRepository )
466 {
467 GitScmProviderRepository gitAncestor = (GitScmProviderRepository) ancestor;
468
469
470 String url = getFetchUrl();
471 String path = url.replaceFirst( gitAncestor.getFetchUrl() + "/", "" );
472
473 if ( !path.equals( url ) )
474 {
475 return path;
476 }
477 }
478 return null;
479 }
480
481
482
483
484 public String toString()
485 {
486
487 if ( fetchInfo == pushInfo )
488 {
489 return getUrl( fetchInfo );
490 }
491 return URL_DELIMITER_FETCH + getUrl( fetchInfo ) + URL_DELIMITER_PUSH + getUrl( pushInfo );
492 }
493
494 }