use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Placement {
InRepo,
Global,
}
pub fn in_repo_root(main_worktree: &Path) -> PathBuf {
main_worktree.join(".worktrees")
}
pub fn global_repo_root(global_root: &Path, repo_name: &str) -> PathBuf {
global_root.join(repo_name)
}
pub fn worktree_path(
placement: Placement,
main_worktree: &Path,
global_root: &Path,
repo_name: &str,
name: &str,
) -> PathBuf {
match placement {
Placement::InRepo => in_repo_root(main_worktree).join(name),
Placement::Global => global_repo_root(global_root, repo_name).join(name),
}
}
pub fn classify(
path: &Path,
main_worktree: &Path,
global_root: &Path,
repo_name: &str,
) -> Option<Placement> {
let path = normalize(path);
let in_repo = normalize(&in_repo_root(main_worktree));
if path.starts_with(&in_repo) {
return Some(Placement::InRepo);
}
let global = normalize(&global_repo_root(global_root, repo_name));
if path.starts_with(&global) {
return Some(Placement::Global);
}
None
}
fn normalize(path: &Path) -> PathBuf {
let mut s = path.to_string_lossy().to_string();
while s.ends_with('/') && s.len() > 1 {
s.pop();
}
PathBuf::from(s)
}
#[cfg(test)]
mod tests {
use super::*;
fn main() -> PathBuf {
PathBuf::from("/proj/vkit-rs")
}
fn global() -> PathBuf {
PathBuf::from("/Users/me/worktrees")
}
#[test]
fn classifies_in_repo() {
let p = PathBuf::from("/proj/vkit-rs/.worktrees/feat-auth");
assert_eq!(
classify(&p, &main(), &global(), "vkit-rs"),
Some(Placement::InRepo)
);
}
#[test]
fn classifies_global() {
let p = PathBuf::from("/Users/me/worktrees/vkit-rs/feat-auth");
assert_eq!(
classify(&p, &main(), &global(), "vkit-rs"),
Some(Placement::Global)
);
}
#[test]
fn rejects_other_paths() {
let p = PathBuf::from("/tmp/odd-worktree");
assert_eq!(classify(&p, &main(), &global(), "vkit-rs"), None);
}
#[test]
fn rejects_other_repo_under_global() {
let p = PathBuf::from("/Users/me/worktrees/other-repo/feat-auth");
assert_eq!(classify(&p, &main(), &global(), "vkit-rs"), None);
}
#[test]
fn builds_paths() {
assert_eq!(
worktree_path(Placement::InRepo, &main(), &global(), "vkit-rs", "feat-auth"),
PathBuf::from("/proj/vkit-rs/.worktrees/feat-auth")
);
assert_eq!(
worktree_path(Placement::Global, &main(), &global(), "vkit-rs", "feat-auth"),
PathBuf::from("/Users/me/worktrees/vkit-rs/feat-auth")
);
}
}