diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/git.rs | 124 | ||||
| -rw-r--r-- | src/sub_commands/init.rs | 13 |
2 files changed, 133 insertions, 4 deletions
| @@ -886,6 +886,64 @@ pub fn nostr_git_url_to_repo_coordinates(url: &str) -> Result<HashSet<Coordinate | |||
| 886 | ); | 886 | ); |
| 887 | } | 887 | } |
| 888 | 888 | ||
| 889 | /** produce error when using local repo or custom protocols */ | ||
| 890 | pub fn convert_clone_url_to_https(url: &str) -> Result<String> { | ||
| 891 | // Strip credentials if present | ||
| 892 | let stripped_url = strip_credentials(url); | ||
| 893 | |||
| 894 | // Check if the URL is already in HTTPS format | ||
| 895 | if stripped_url.starts_with("https://") { | ||
| 896 | return Ok(stripped_url); | ||
| 897 | } | ||
| 898 | // Convert http:// to https:// | ||
| 899 | else if stripped_url.starts_with("http://") { | ||
| 900 | return Ok(stripped_url.replace("http://", "https://")); | ||
| 901 | } | ||
| 902 | // Check if the URL starts with SSH | ||
| 903 | else if stripped_url.starts_with("ssh://") { | ||
| 904 | // Convert SSH to HTTPS | ||
| 905 | let parts: Vec<&str> = stripped_url | ||
| 906 | .trim_start_matches("ssh://") | ||
| 907 | .split('/') | ||
| 908 | .collect(); | ||
| 909 | if parts.len() >= 2 { | ||
| 910 | // Construct the HTTPS URL | ||
| 911 | return Ok(format!("https://{}/{}", parts[0], parts[1..].join("/"))); | ||
| 912 | } | ||
| 913 | bail!("Invalid SSH URL format: {}", url); | ||
| 914 | } | ||
| 915 | // Convert ftp:// to https:// | ||
| 916 | else if stripped_url.starts_with("ftp://") { | ||
| 917 | return Ok(stripped_url.replace("ftp://", "https://")); | ||
| 918 | } | ||
| 919 | // Convert git:// to https:// | ||
| 920 | else if stripped_url.starts_with("git://") { | ||
| 921 | return Ok(stripped_url.replace("git://", "https://")); | ||
| 922 | } | ||
| 923 | |||
| 924 | // If the URL is neither HTTPS, SSH, nor git@, return an error | ||
| 925 | bail!("Unsupported URL protocol: {}", url); | ||
| 926 | } | ||
| 927 | |||
| 928 | // Function to strip username and password from the URL | ||
| 929 | fn strip_credentials(url: &str) -> String { | ||
| 930 | if let Some(pos) = url.find("://") { | ||
| 931 | let (protocol, rest) = url.split_at(pos + 3); // Split at "://" | ||
| 932 | let rest_parts: Vec<&str> = rest.split('@').collect(); | ||
| 933 | if rest_parts.len() > 1 { | ||
| 934 | // If there are credentials, return the URL without them | ||
| 935 | return format!("{}{}", protocol, rest_parts[1]); | ||
| 936 | } | ||
| 937 | } else if let Some(at_pos) = url.find('@') { | ||
| 938 | // Handle user@host:path format | ||
| 939 | let (_, rest) = url.split_at(at_pos); | ||
| 940 | // This is a git@ syntax | ||
| 941 | let host_and_repo = &rest[1..]; // Skip the ':' | ||
| 942 | return format!("ssh://{}", host_and_repo.replace(':', "/")); | ||
| 943 | } | ||
| 944 | url.to_string() // Return the original URL if no credentials are found | ||
| 945 | } | ||
| 946 | |||
| 889 | #[cfg(test)] | 947 | #[cfg(test)] |
| 890 | mod tests { | 948 | mod tests { |
| 891 | use std::fs; | 949 | use std::fs; |
| @@ -2366,4 +2424,70 @@ mod tests { | |||
| 2366 | Ok(()) | 2424 | Ok(()) |
| 2367 | } | 2425 | } |
| 2368 | } | 2426 | } |
| 2427 | mod convert_clone_url_to_https { | ||
| 2428 | use super::*; | ||
| 2429 | |||
| 2430 | #[test] | ||
| 2431 | fn test_https_url() { | ||
| 2432 | let url = "https://github.com/user/repo.git"; | ||
| 2433 | let result = convert_clone_url_to_https(url).unwrap(); | ||
| 2434 | assert_eq!(result, "https://github.com/user/repo.git"); | ||
| 2435 | } | ||
| 2436 | |||
| 2437 | #[test] | ||
| 2438 | fn test_http_url() { | ||
| 2439 | let url = "http://github.com/user/repo.git"; | ||
| 2440 | let result = convert_clone_url_to_https(url).unwrap(); | ||
| 2441 | assert_eq!(result, "https://github.com/user/repo.git"); | ||
| 2442 | } | ||
| 2443 | |||
| 2444 | #[test] | ||
| 2445 | fn test_http_url_with_credentials() { | ||
| 2446 | let url = "http://username:password@github.com/user/repo.git"; | ||
| 2447 | let result = convert_clone_url_to_https(url).unwrap(); | ||
| 2448 | assert_eq!(result, "https://github.com/user/repo.git"); | ||
| 2449 | } | ||
| 2450 | |||
| 2451 | #[test] | ||
| 2452 | fn test_git_at_url() { | ||
| 2453 | let url = "git@github.com:user/repo.git"; | ||
| 2454 | let result = convert_clone_url_to_https(url).unwrap(); | ||
| 2455 | assert_eq!(result, "https://github.com/user/repo.git"); | ||
| 2456 | } | ||
| 2457 | |||
| 2458 | #[test] | ||
| 2459 | fn test_user_at_url() { | ||
| 2460 | let url = "user1@github.com:user/repo.git"; | ||
| 2461 | let result = convert_clone_url_to_https(url).unwrap(); | ||
| 2462 | assert_eq!(result, "https://github.com/user/repo.git"); | ||
| 2463 | } | ||
| 2464 | |||
| 2465 | #[test] | ||
| 2466 | fn test_ssh_url() { | ||
| 2467 | let url = "ssh://github.com/user/repo.git"; | ||
| 2468 | let result = convert_clone_url_to_https(url).unwrap(); | ||
| 2469 | assert_eq!(result, "https://github.com/user/repo.git"); | ||
| 2470 | } | ||
| 2471 | |||
| 2472 | #[test] | ||
| 2473 | fn test_ftp_url() { | ||
| 2474 | let url = "ftp://example.com/repo.git"; | ||
| 2475 | let result = convert_clone_url_to_https(url).unwrap(); | ||
| 2476 | assert_eq!(result, "https://example.com/repo.git"); | ||
| 2477 | } | ||
| 2478 | |||
| 2479 | #[test] | ||
| 2480 | fn test_git_protocol_url() { | ||
| 2481 | let url = "git://example.com/repo.git"; | ||
| 2482 | let result = convert_clone_url_to_https(url).unwrap(); | ||
| 2483 | assert_eq!(result, "https://example.com/repo.git"); | ||
| 2484 | } | ||
| 2485 | |||
| 2486 | #[test] | ||
| 2487 | fn test_invalid_url() { | ||
| 2488 | let url = "unsupported://example.com/repo.git"; | ||
| 2489 | let result = convert_clone_url_to_https(url); | ||
| 2490 | assert!(result.is_err()); | ||
| 2491 | } | ||
| 2492 | } | ||
| 2369 | } | 2493 | } |
diff --git a/src/sub_commands/init.rs b/src/sub_commands/init.rs index 4958536..5b7e03d 100644 --- a/src/sub_commands/init.rs +++ b/src/sub_commands/init.rs | |||
| @@ -13,7 +13,7 @@ use crate::{ | |||
| 13 | cli::Cli, | 13 | cli::Cli, |
| 14 | cli_interactor::{Interactor, InteractorPrompt, PromptInputParms}, | 14 | cli_interactor::{Interactor, InteractorPrompt, PromptInputParms}, |
| 15 | client::{fetching_with_report, get_repo_ref_from_cache, Connect}, | 15 | client::{fetching_with_report, get_repo_ref_from_cache, Connect}, |
| 16 | git::{Repo, RepoActions}, | 16 | git::{convert_clone_url_to_https, Repo, RepoActions}, |
| 17 | login, | 17 | login, |
| 18 | repo_ref::{ | 18 | repo_ref::{ |
| 19 | extract_pks, get_repo_config_from_yaml, save_repo_config_to_yaml, | 19 | extract_pks, get_repo_config_from_yaml, save_repo_config_to_yaml, |
| @@ -159,11 +159,16 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | |||
| 159 | Interactor::default() | 159 | Interactor::default() |
| 160 | .input( | 160 | .input( |
| 161 | PromptInputParms::default() | 161 | PromptInputParms::default() |
| 162 | .with_prompt("clone url") | 162 | .with_prompt("clone url (for fetch)") |
| 163 | .with_default(if let Some(repo_ref) = &repo_ref { | 163 | .with_default(if let Some(repo_ref) = &repo_ref { |
| 164 | repo_ref.git_server.clone().join(" ") | 164 | repo_ref.git_server.clone().join(" ") |
| 165 | } else if let Ok(git_repo) = git_repo.get_origin_url() { | 165 | } else if let Ok(url) = git_repo.get_origin_url() { |
| 166 | git_repo | 166 | if let Ok(fetch_url) = convert_clone_url_to_https(&url) { |
| 167 | fetch_url | ||
| 168 | } else { | ||
| 169 | // local repo or custom protocol | ||
| 170 | url | ||
| 171 | } | ||
| 167 | } else { | 172 | } else { |
| 168 | String::new() | 173 | String::new() |
| 169 | }), | 174 | }), |