use std::path::{Path, PathBuf};
pub fn sanitize_branch_name(branch: &str) -> String {
let mut result = branch.replace('/', "-");
result = result.trim_start_matches('.').to_string();
while result.contains("--") {
result = result.replace("--", "-");
}
result = result.trim_matches('-').to_string();
if result.is_empty() {
result = "branch".to_string();
}
result
}
pub fn worktree_dir(bare_repo: &Path, branch: &str, prefix: &str) -> PathBuf {
let parent = bare_repo
.parent()
.expect("bare repo must have a parent dir");
let sanitized = sanitize_branch_name(branch);
let dir_name = if prefix.is_empty() {
sanitized
} else {
format!("{prefix}_{sanitized}")
};
parent.join(dir_name)
}
pub fn repo_name_from_url(url: &str) -> String {
let name = url
.trim_end_matches('/')
.rsplit('/')
.next()
.unwrap_or("repo");
name.strip_suffix(".git").unwrap_or(name).to_string()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sanitize_simple_branch() {
assert_eq!(sanitize_branch_name("main"), "main");
}
#[test]
fn sanitize_slashes() {
assert_eq!(sanitize_branch_name("feature/my-thing"), "feature-my-thing");
}
#[test]
fn sanitize_leading_dot() {
assert_eq!(sanitize_branch_name(".hidden"), "hidden");
}
#[test]
fn sanitize_consecutive_dashes() {
assert_eq!(sanitize_branch_name("a//b"), "a-b");
}
#[test]
fn worktree_dir_with_prefix() {
let bare = Path::new("/repos/myproject/repo.git");
assert_eq!(
worktree_dir(bare, "feature/login", "mp"),
PathBuf::from("/repos/myproject/mp_feature-login")
);
}
#[test]
fn worktree_dir_without_prefix() {
let bare = Path::new("/repos/myproject/repo.git");
assert_eq!(
worktree_dir(bare, "feature/login", ""),
PathBuf::from("/repos/myproject/feature-login")
);
}
#[test]
fn repo_name_from_https_url() {
assert_eq!(
repo_name_from_url("https://github.com/user/repo.git"),
"repo"
);
}
#[test]
fn repo_name_from_ssh_url() {
assert_eq!(
repo_name_from_url("git@github.com:user/my-project.git"),
"my-project"
);
}
#[test]
fn repo_name_without_git_suffix() {
assert_eq!(repo_name_from_url("https://github.com/user/repo"), "repo");
}
#[test]
fn repo_name_trailing_slash() {
assert_eq!(
repo_name_from_url("https://github.com/user/repo.git/"),
"repo"
);
}
}