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