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
376 int indexAt = url.lastIndexOf( '@' );
377 if ( indexAt >= 0 )
378 {
379 String userInfo = url.substring( 0, indexAt );
380 int indexPwdSep = userInfo.indexOf( ':' );
381 if ( indexPwdSep < 0 )
382 {
383 repoUrl.setUserName( userInfo );
384 }
385 else
386 {
387 repoUrl.setUserName( userInfo.substring( 0, indexPwdSep ) );
388 repoUrl.setPassword( userInfo.substring( indexPwdSep + 1 ) );
389 }
390
391 url = url.substring( indexAt + 1 );
392 }
393 return url;
394 }
395
396
397
398
399
400
401
402
403
404
405 private String parseHostAndPort( RepositoryUrl repoUrl, String url )
406 throws ScmException
407 {
408
409 repoUrl.setPort( "" );
410 repoUrl.setHost( "" );
411
412 if ( PROTOCOL_FILE.equals( repoUrl.getProtocol() ) )
413 {
414
415 return url;
416 }
417 else
418 {
419
420 Matcher hostAndPortMatcher = HOST_AND_PORT_EXTRACTOR.matcher( url );
421 if ( hostAndPortMatcher.matches() )
422 {
423 if ( hostAndPortMatcher.groupCount() > 1 && hostAndPortMatcher.group( 1 ) != null )
424 {
425 repoUrl.setHost( hostAndPortMatcher.group( 1 ) );
426 }
427 if ( hostAndPortMatcher.groupCount() > 2 && hostAndPortMatcher.group( 2 ) != null )
428 {
429 repoUrl.setPort( hostAndPortMatcher.group( 2 ) );
430 }
431
432 StringBuilder computedUrl = new StringBuilder();
433 if ( hostAndPortMatcher.group( hostAndPortMatcher.groupCount() - 1 ) != null )
434 {
435 computedUrl.append( hostAndPortMatcher.group( hostAndPortMatcher.groupCount() - 1 ) );
436 }
437 if ( hostAndPortMatcher.group( hostAndPortMatcher.groupCount() ) != null )
438 {
439 computedUrl.append( hostAndPortMatcher.group( hostAndPortMatcher.groupCount() ) );
440 }
441 return computedUrl.toString();
442 }
443 else
444 {
445
446 return url;
447 }
448 }
449 }
450
451
452
453
454
455 public String getRelativePath( ScmProviderRepository ancestor )
456 {
457 if ( ancestor instanceof GitScmProviderRepository )
458 {
459 GitScmProviderRepository gitAncestor = (GitScmProviderRepository) ancestor;
460
461
462 String url = getFetchUrl();
463 String path = url.replaceFirst( gitAncestor.getFetchUrl() + "/", "" );
464
465 if ( !path.equals( url ) )
466 {
467 return path;
468 }
469 }
470 return null;
471 }
472
473
474
475
476 public String toString()
477 {
478
479 if ( fetchInfo == pushInfo )
480 {
481 return getUrl( fetchInfo );
482 }
483 return URL_DELIMITER_FETCH + getUrl( fetchInfo ) + URL_DELIMITER_PUSH + getUrl( pushInfo );
484 }
485
486 }