From 9161f5799de6cfa3d2d3fe127d19d8a59c5347f4 Mon Sep 17 00:00:00 2001 From: Tim Schubert Date: Sun, 24 Aug 2025 14:41:17 +0200 Subject: [PATCH] feat: support short git URLs Something like git@github.com:dadada/dadada.git --- src/main.rs | 2 +- src/root.rs | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 07be249..b8f1241 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,7 +55,7 @@ fn main() -> Result<()> { match cli.command { Commands::Resolve { root, repo } => { let root = SrcRoot::new(resolve_root(root)?); - println!("{}", root.resolve_repo(repo)?.as_ref().display()); + println!("{}", root.resolve_repo(repo.as_str())?.as_ref().display()); } Commands::Setup { root } => { let root = resolve_root(root)?; diff --git a/src/root.rs b/src/root.rs index 259f692..61e405a 100644 --- a/src/root.rs +++ b/src/root.rs @@ -75,12 +75,12 @@ impl SrcRoot { /// # Errors /// File system errors - pub fn resolve_repo(&self, arg: String) -> Result> { - if let Ok(url) = Url::parse(&arg) { - self.ensure_repo_checkout(&url) + pub fn resolve_repo(&self, arg: &str) -> Result> { + if let Some(found) = self.search_repo(arg)? { + Ok(found) } else { - let slug: OsString = arg.into(); - self.search_repo(slug)?.context("Repo not found") + let url = normalize_url(arg)?; + self.ensure_repo_checkout(&url) } } @@ -89,3 +89,34 @@ impl SrcRoot { Self { root_path: path } } } + +fn normalize_url(url: &str) -> Result { + match Url::parse(url) { + Ok(url) => Ok(url), + Err(e @ url::ParseError::RelativeUrlWithoutBase) => { + let normalized_url = &format!("ssh://{url}"); + normalize_ssh(e, normalized_url) + } + Err(e @ url::ParseError::InvalidPort) => normalize_ssh(e, url), + Err(e) => Err(e.into()), + } +} + +fn normalize_ssh(e: url::ParseError, url: &str) -> Result { + match Url::parse(url) { + Ok(o) => Ok(o), + Err(url::ParseError::InvalidPort) => { + let mut split = url.splitn(3, ':'); + let mut normalized_url = String::with_capacity(url.len()); + normalized_url.push_str(split.next().context(e)?); + normalized_url.push(':'); + normalized_url.push_str(split.next().context(e)?); + normalized_url.push('/'); + let tail = split.next().context(e)?; + normalized_url.push_str(tail); + let normalized_url = Url::parse(&normalized_url)?; + Ok(normalized_url) + } + Err(e) => Err(e.into()), + } +}