diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-05-06 10:42:02 +0100 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-05-06 10:51:23 +0100 |
| commit | b2df89a1f57c136d710962439a86e90fa5249400 (patch) | |
| tree | b546f9ab7d723352676f174f6444b5f0b7dafcb3 /src/lib/git/nostr_url.rs | |
| parent | a744f4aae9ffee9dd246090bef486b09433778d0 (diff) | |
fix(clone_url): fix custom ports
only use custom port on specified protocol (ie. http, https or ssh)
ignore custom port on when trying other protocols
specify `ssh://` prefix when using custom port as otherwise it can
be ignored
Diffstat (limited to 'src/lib/git/nostr_url.rs')
| -rw-r--r-- | src/lib/git/nostr_url.rs | 127 |
1 files changed, 86 insertions, 41 deletions
diff --git a/src/lib/git/nostr_url.rs b/src/lib/git/nostr_url.rs index fe58962..a9b08eb 100644 --- a/src/lib/git/nostr_url.rs +++ b/src/lib/git/nostr_url.rs | |||
| @@ -428,10 +428,12 @@ impl CloneUrl { | |||
| 428 | 428 | ||
| 429 | url.set_path(&self.path); | 429 | url.set_path(&self.path); |
| 430 | 430 | ||
| 431 | // Set the port if present | 431 | // Set custom port |
| 432 | if let Some(port) = self.port { | 432 | if let Some(port) = self.port { |
| 433 | url.set_port(Some(port)) | 433 | if protocols_match(&self.protocol, protocol) { |
| 434 | .map_err(|_| anyhow!("failed to add port"))?; | 434 | url.set_port(Some(port)) |
| 435 | .map_err(|_| anyhow!("failed to add port"))?; | ||
| 436 | } | ||
| 435 | } | 437 | } |
| 436 | 438 | ||
| 437 | // Set the query parameters if present | 439 | // Set the query parameters if present |
| @@ -451,7 +453,9 @@ impl CloneUrl { | |||
| 451 | "ssh://", | 453 | "ssh://", |
| 452 | format!("{}@", user.as_deref().unwrap_or("git")).as_str(), | 454 | format!("{}@", user.as_deref().unwrap_or("git")).as_str(), |
| 453 | ); | 455 | ); |
| 454 | if !contains_port(&formatted_url) { | 456 | if url.port().is_some() { |
| 457 | formatted_url = format!("ssh://{}", formatted_url); | ||
| 458 | } else { | ||
| 455 | formatted_url = replace_first_occurrence(&formatted_url, '/', ':'); | 459 | formatted_url = replace_first_occurrence(&formatted_url, '/', ':'); |
| 456 | } | 460 | } |
| 457 | } else if *protocol == ServerProtocol::Unspecified { | 461 | } else if *protocol == ServerProtocol::Unspecified { |
| @@ -547,6 +551,12 @@ fn strip_credentials(url: &str) -> String { | |||
| 547 | url.to_string() // Return the original URL if no credentials are found | 551 | url.to_string() // Return the original URL if no credentials are found |
| 548 | } | 552 | } |
| 549 | 553 | ||
| 554 | fn protocols_match(a: &ServerProtocol, b: &ServerProtocol) -> bool { | ||
| 555 | let https = [ServerProtocol::Https, ServerProtocol::UnauthHttps]; | ||
| 556 | let http = [ServerProtocol::Http, ServerProtocol::UnauthHttp]; | ||
| 557 | https.contains(a) && https.contains(b) || http.contains(a) && http.contains(b) || a.eq(b) | ||
| 558 | } | ||
| 559 | |||
| 550 | #[cfg(test)] | 560 | #[cfg(test)] |
| 551 | mod tests { | 561 | mod tests { |
| 552 | use super::*; | 562 | use super::*; |
| @@ -604,14 +614,63 @@ mod tests { | |||
| 604 | assert_eq!(result, "git@github.com:user/repo.git"); | 614 | assert_eq!(result, "git@github.com:user/repo.git"); |
| 605 | } | 615 | } |
| 606 | 616 | ||
| 607 | #[test] | 617 | mod only_includes_custom_port_on_specified_protocol { |
| 608 | fn format_as_ssh_includes_port() { | 618 | use super::*; |
| 609 | let result = "https://github.com:1000/user/repo.git" | 619 | |
| 610 | .parse::<CloneUrl>() | 620 | #[test] |
| 611 | .unwrap() | 621 | fn format_as_http_includes_custom_http_port() { |
| 612 | .format_as(&ServerProtocol::Ssh, &None) | 622 | let result = "https://github.com:1000/user/repo.git" |
| 613 | .unwrap(); | 623 | .parse::<CloneUrl>() |
| 614 | assert_eq!(result, "git@github.com:1000/user/repo.git"); | 624 | .unwrap() |
| 625 | .format_as(&ServerProtocol::Https, &None) | ||
| 626 | .unwrap(); | ||
| 627 | assert_eq!(result, "https://github.com:1000/user/repo.git"); | ||
| 628 | } | ||
| 629 | |||
| 630 | #[test] | ||
| 631 | fn format_as_ssh_excludes_custom_http_port() { | ||
| 632 | let result = "https://github.com:1000/user/repo.git" | ||
| 633 | .parse::<CloneUrl>() | ||
| 634 | .unwrap() | ||
| 635 | .format_as(&ServerProtocol::Ssh, &None) | ||
| 636 | .unwrap(); | ||
| 637 | assert_eq!(result, "git@github.com:user/repo.git"); | ||
| 638 | } | ||
| 639 | |||
| 640 | #[test] | ||
| 641 | fn format_as_ssh_includes_custom_ssh_port() { | ||
| 642 | // 29418 is the port used by gerrit and seen used by gitea instances | ||
| 643 | let result = "ssh://git@github.com:29418/user/repo.git" | ||
| 644 | .parse::<CloneUrl>() | ||
| 645 | .unwrap() | ||
| 646 | .format_as(&ServerProtocol::Ssh, &None) | ||
| 647 | .unwrap(); | ||
| 648 | // need this format | ||
| 649 | assert_eq!(result, "ssh://git@github.com:29418/user/repo.git"); | ||
| 650 | } | ||
| 651 | |||
| 652 | #[test] | ||
| 653 | fn format_as_http_excludes_custom_ssh_port() { | ||
| 654 | let result = "ssh://git@github.com:29418/user/repo.git" | ||
| 655 | .parse::<CloneUrl>() | ||
| 656 | .unwrap() | ||
| 657 | .format_as(&ServerProtocol::Https, &None) | ||
| 658 | .unwrap(); | ||
| 659 | // need this format | ||
| 660 | assert_eq!(result, "https://github.com/user/repo.git"); | ||
| 661 | } | ||
| 662 | |||
| 663 | #[test] | ||
| 664 | fn always_format_ssh_with_port_with_prefix() { | ||
| 665 | // 29418 is the port used by gerrit and seen used by gitea instances | ||
| 666 | let result = "git@github.com:29418/user/repo.git" | ||
| 667 | .parse::<CloneUrl>() | ||
| 668 | .unwrap() | ||
| 669 | .format_as(&ServerProtocol::Ssh, &None) | ||
| 670 | .unwrap(); | ||
| 671 | // need this format | ||
| 672 | assert_eq!(result, "ssh://git@github.com:29418/user/repo.git"); | ||
| 673 | } | ||
| 615 | } | 674 | } |
| 616 | 675 | ||
| 617 | #[test] | 676 | #[test] |
| @@ -641,13 +700,13 @@ mod tests { | |||
| 641 | use super::*; | 700 | use super::*; |
| 642 | 701 | ||
| 643 | #[test] | 702 | #[test] |
| 644 | fn port() { | 703 | fn port_ignored() { |
| 645 | let result = "github.com:1000/user/repo.git" | 704 | let result = "github.com:1000/user/repo.git" |
| 646 | .parse::<CloneUrl>() | 705 | .parse::<CloneUrl>() |
| 647 | .unwrap() | 706 | .unwrap() |
| 648 | .format_as(&ServerProtocol::Https, &None) | 707 | .format_as(&ServerProtocol::Https, &None) |
| 649 | .unwrap(); | 708 | .unwrap(); |
| 650 | assert_eq!(result, "https://github.com:1000/user/repo.git"); | 709 | assert_eq!(result, "https://github.com/user/repo.git"); |
| 651 | } | 710 | } |
| 652 | 711 | ||
| 653 | #[test] | 712 | #[test] |
| @@ -687,10 +746,7 @@ mod tests { | |||
| 687 | .unwrap() | 746 | .unwrap() |
| 688 | .format_as(&ServerProtocol::Https, &None) | 747 | .format_as(&ServerProtocol::Https, &None) |
| 689 | .unwrap(); | 748 | .unwrap(); |
| 690 | assert_eq!( | 749 | assert_eq!(result, "https://github.com/repo.git?version=1.0#section1"); |
| 691 | result, | ||
| 692 | "https://github.com:2222/repo.git?version=1.0#section1" | ||
| 693 | ); | ||
| 694 | } | 750 | } |
| 695 | } | 751 | } |
| 696 | 752 | ||
| @@ -794,26 +850,6 @@ mod tests { | |||
| 794 | } | 850 | } |
| 795 | 851 | ||
| 796 | #[test] | 852 | #[test] |
| 797 | fn port_specified_with_path() { | ||
| 798 | let result = "user@github.com:2222/repo.git" | ||
| 799 | .parse::<CloneUrl>() | ||
| 800 | .unwrap() | ||
| 801 | .format_as(&ServerProtocol::Https, &None) | ||
| 802 | .unwrap(); | ||
| 803 | assert_eq!(result, "https://github.com:2222/repo.git"); | ||
| 804 | } | ||
| 805 | |||
| 806 | #[test] | ||
| 807 | fn port_specified_without_path() { | ||
| 808 | let result = "user@github.com:2222" | ||
| 809 | .parse::<CloneUrl>() | ||
| 810 | .unwrap() | ||
| 811 | .format_as(&ServerProtocol::Https, &None) | ||
| 812 | .unwrap(); | ||
| 813 | assert_eq!(result, "https://github.com:2222"); | ||
| 814 | } | ||
| 815 | |||
| 816 | #[test] | ||
| 817 | fn path_with_fragment() { | 853 | fn path_with_fragment() { |
| 818 | let result = "user1@github.com:/user/repo.git#readme" | 854 | let result = "user1@github.com:/user/repo.git#readme" |
| 819 | .parse::<CloneUrl>() | 855 | .parse::<CloneUrl>() |
| @@ -834,17 +870,26 @@ mod tests { | |||
| 834 | } | 870 | } |
| 835 | 871 | ||
| 836 | #[test] | 872 | #[test] |
| 837 | fn port_with_parameters_and_fragment() { | 873 | fn port_with_parameters_and_fragment_ssh() { |
| 838 | let result = "user@github.com:2222/repo.git?version=1.0#section1" | 874 | let result = "user@github.com:2222/repo.git?version=1.0#section1" |
| 839 | .parse::<CloneUrl>() | 875 | .parse::<CloneUrl>() |
| 840 | .unwrap() | 876 | .unwrap() |
| 841 | .format_as(&ServerProtocol::Https, &None) | 877 | .format_as(&ServerProtocol::Ssh, &None) |
| 842 | .unwrap(); | 878 | .unwrap(); |
| 843 | assert_eq!( | 879 | assert_eq!( |
| 844 | result, | 880 | result, |
| 845 | "https://github.com:2222/repo.git?version=1.0#section1" | 881 | "ssh://git@github.com:2222/repo.git?version=1.0#section1" |
| 846 | ); | 882 | ); |
| 847 | } | 883 | } |
| 884 | #[test] | ||
| 885 | fn port_with_parameters_and_fragment_https() { | ||
| 886 | let result = "user@github.com:2222/repo.git?version=1.0#section1" | ||
| 887 | .parse::<CloneUrl>() | ||
| 888 | .unwrap() | ||
| 889 | .format_as(&ServerProtocol::Https, &None) | ||
| 890 | .unwrap(); | ||
| 891 | assert_eq!(result, "https://github.com/repo.git?version=1.0#section1"); | ||
| 892 | } | ||
| 848 | } | 893 | } |
| 849 | 894 | ||
| 850 | #[test] | 895 | #[test] |