use crate::error::Result;
use crate::git::GitWorktree;
use colored::*;
pub struct ListCommand {
pub names_only: bool,
}
impl ListCommand {
pub fn new(names_only: bool) -> Self {
Self { names_only }
}
pub fn execute(&self) -> Result<()> {
let git_worktree = GitWorktree::new()?;
let worktrees = git_worktree.list_worktrees()?;
if worktrees.is_empty() {
if !self.names_only {
println!("No worktrees found.");
}
return Ok(());
}
if self.names_only {
for worktree in worktrees {
println!("{}", worktree.branch);
}
} else {
println!(
"{:<30} {:<50}",
"BRANCH".blue().bold(),
"PATH".blue().bold()
);
println!("{}", "-".repeat(80).bright_black());
for worktree in worktrees {
println!(
"{:<30} {:<50}",
worktree.branch.green(),
worktree.path.display().to_string().yellow()
);
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
use std::fs;
use std::process::Command;
fn setup_git_repo_with_worktree() -> tempfile::TempDir {
let temp_dir = tempdir().unwrap();
let repo_path = temp_dir.path();
Command::new("git")
.args(&["init"])
.current_dir(repo_path)
.output()
.expect("Failed to init git repo");
Command::new("git")
.args(&["config", "user.name", "Test User"])
.current_dir(repo_path)
.output()
.unwrap();
Command::new("git")
.args(&["config", "user.email", "test@example.com"])
.current_dir(repo_path)
.output()
.unwrap();
fs::write(repo_path.join("README.md"), "# Test Repo").unwrap();
Command::new("git")
.args(&["add", "."])
.current_dir(repo_path)
.output()
.unwrap();
Command::new("git")
.args(&["commit", "-m", "Initial commit"])
.current_dir(repo_path)
.output()
.unwrap();
let worktree_path = repo_path.join("feature-test");
Command::new("git")
.args(&["worktree", "add", "-b", "feature-test", &worktree_path.to_string_lossy()])
.current_dir(repo_path)
.output()
.unwrap();
temp_dir
}
#[test]
fn test_list_command_new_creates_instance() {
let cmd = ListCommand::new(true);
assert_eq!(cmd.names_only, true);
let cmd = ListCommand::new(false);
assert_eq!(cmd.names_only, false);
}
#[test]
fn test_list_command_fails_without_git_repo() {
let temp_dir = tempdir().unwrap();
std::env::set_current_dir(temp_dir.path()).unwrap();
let cmd = ListCommand::new(false);
let result = cmd.execute();
assert!(result.is_err());
}
#[test]
fn test_list_command_empty_repo_shows_no_worktrees() {
let temp_dir = tempdir().unwrap();
let repo_path = temp_dir.path();
Command::new("git")
.args(&["init"])
.current_dir(repo_path)
.output()
.expect("Failed to init git repo");
std::env::set_current_dir(repo_path).unwrap();
let cmd = ListCommand::new(false);
let result = cmd.execute();
assert!(result.is_ok());
}
#[test]
fn test_list_command_names_only_flag() {
let temp_dir = setup_git_repo_with_worktree();
std::env::set_current_dir(temp_dir.path()).unwrap();
let cmd = ListCommand::new(true);
let result = cmd.execute();
assert!(result.is_ok());
let cmd = ListCommand::new(false);
let result = cmd.execute();
assert!(result.is_ok());
}
}