| 442 | } |
| 443 | |
| 444 | char *url_parse(const char *url_orig, struct url_info *out_info) |
| 445 | { |
| 446 | struct strbuf url; |
| 447 | char *host, *separator; |
| 448 | char *detached, *normalized; |
| 449 | char *url_decoded; |
| 450 | enum url_scheme scheme = URL_SCHEME_LOCAL; |
| 451 | struct url_info local_info; |
| 452 | struct url_info *info = out_info ? out_info : &local_info; |
| 453 | bool scp_syntax = false; |
| 454 | |
| 455 | if (is_url(url_orig)) |
| 456 | url_decoded = url_decode(url_orig); |
| 457 | else |
| 458 | url_decoded = xstrdup(url_orig); |
| 459 | |
| 460 | strbuf_init(&url, strlen(url_decoded) + sizeof("ssh://")); |
| 461 | strbuf_addstr(&url, url_decoded); |
| 462 | free(url_decoded); |
| 463 | |
| 464 | host = strstr(url.buf, "://"); |
| 465 | if (host) { |
| 466 | /* |
| 467 | * Temporarily NUL-terminate the scheme name |
| 468 | * so we can pass it to url_get_scheme(), |
| 469 | * then restore the ':' so the buffer |
| 470 | * is intact for url_normalize() below. |
| 471 | */ |
| 472 | char saved = *host; |
| 473 | *host = '\0'; |
| 474 | scheme = url_get_scheme(url.buf); |
| 475 | *host = saved; |
| 476 | host += 3; |
| 477 | } else { |
| 478 | if (!url_is_local_not_ssh(url.buf)) { |
| 479 | scp_syntax = true; |
| 480 | scheme = URL_SCHEME_SSH; |
| 481 | strbuf_insertstr(&url, 0, "ssh://"); |
| 482 | host = url.buf + strlen("ssh://"); |
| 483 | } |
| 484 | } |
| 485 | |
| 486 | /* |
| 487 | * Path starts after ':' in scp style SSH URLs. |
| 488 | * |
| 489 | * The host portion can begin with an optional "user@", |
| 490 | * and the host itself can be wrapped in '[' ']' brackets. |
| 491 | * The bracket form is git's legacy way of supporting: |
| 492 | * |
| 493 | * - IPv6 literals: [::1]:repo |
| 494 | * - host:port pairs in the short form: [myhost:123]:src |
| 495 | * - Plain hostnames that happen to need bracketing: [host]:path |
| 496 | * |
| 497 | * Treat '[' followed by 0 or 1 inner colons as the host:port |
| 498 | * or plain hostname form and strip the brackets so url_normalize |
| 499 | * sees host[:port] natively. Two or more inner colons mark an |
| 500 | * IPv6 literal: keep the brackets for url_normalize to recognize. |
| 501 | * |
no test coverage detected