pub fn urls_match(a: &str, b: &str) -> bool {
normalize_repo_url(a) == normalize_repo_url(b)
}
fn normalize_repo_url(url: &str) -> String {
let https_form = if let Some(rest) = url.strip_prefix("git@") {
if let Some((host, path)) = rest.split_once(':') {
format!("https://{host}/{path}")
} else {
url.to_owned()
}
} else {
url.to_owned()
};
https_form
.trim_end_matches('/')
.trim_end_matches(".git")
.to_lowercase()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn urls_match_normalises_variants() {
assert!(
urls_match(
"git@github.com:owner/repo.git",
"https://github.com/owner/repo"
),
"ssh↔https must match"
);
assert!(
urls_match(
"https://github.com/owner/repo/",
"https://github.com/owner/repo"
),
"trailing slash must be ignored"
);
assert!(
urls_match(
"https://github.com/owner/repo.git",
"https://github.com/owner/repo"
),
".git suffix must be stripped"
);
assert!(
urls_match(
"HTTPS://GitHub.com/Owner/Repo",
"https://github.com/owner/repo"
),
"comparison must be case-insensitive"
);
assert!(
!urls_match(
"https://github.com/owner/repo-a",
"https://github.com/owner/repo-b"
),
"distinct repos must not match"
);
}
}