diff --git a/Cargo.lock b/Cargo.lock index ac1e4edabe..3167456349 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5131,6 +5131,7 @@ dependencies = [ "log", "parking_lot", "pretty_assertions", + "regex", "rope", "serde", "serde_json", diff --git a/crates/git/Cargo.toml b/crates/git/Cargo.toml index c0f43e08a8..d31538353e 100644 --- a/crates/git/Cargo.toml +++ b/crates/git/Cargo.toml @@ -21,6 +21,7 @@ gpui.workspace = true http_client.workspace = true log.workspace = true parking_lot.workspace = true +regex.workspace = true rope.workspace = true serde.workspace = true smol.workspace = true diff --git a/crates/git/src/remote.rs b/crates/git/src/remote.rs index 430836fcf3..e9814afc51 100644 --- a/crates/git/src/remote.rs +++ b/crates/git/src/remote.rs @@ -1,17 +1,23 @@ +use std::sync::LazyLock; + use derive_more::Deref; +use regex::Regex; use url::Url; /// The URL to a Git remote. #[derive(Debug, PartialEq, Eq, Clone, Deref)] pub struct RemoteUrl(Url); +static USERNAME_REGEX: LazyLock = + LazyLock::new(|| Regex::new(r"^[0-9a-zA-Z\-_]+@").expect("Failed to create USERNAME_REGEX")); + impl std::str::FromStr for RemoteUrl { type Err = url::ParseError; fn from_str(input: &str) -> Result { - if input.starts_with("git@") { + if USERNAME_REGEX.is_match(input) { // Rewrite remote URLs like `git@github.com:user/repo.git` to `ssh://git@github.com/user/repo.git` - let ssh_url = input.replacen(':', "/", 1).replace("git@", "ssh://git@"); + let ssh_url = format!("ssh://{}", input.replacen(':', "/", 1)); Ok(RemoteUrl(Url::parse(&ssh_url)?)) } else { Ok(RemoteUrl(Url::parse(input)?)) @@ -40,6 +46,12 @@ mod tests { "github.com", "/octocat/zed.git", ), + ( + "org-000000@github.com:octocat/zed.git", + "ssh", + "github.com", + "/octocat/zed.git", + ), ( "ssh://git@github.com/octocat/zed.git", "ssh",