use anyhow::{Context, Result};
use chrono::{DateTime, Utc};
use std::io::IsTerminal;
use std::path::PathBuf;
use std::process::Command;
use crate::color;
use crate::domain::worktree::{
display_path, format_worktree_table, get_last_commit_time, parse_simple_worktree_entries,
parse_worktree_entries,
};
pub fn cmd_list(show_path: bool, color_mode: color::ColorMode) -> Result<()> {
let output = Command::new("git")
.args(["worktree", "list", "--porcelain"])
.output()
.context("Failed to execute git worktree list --porcelain")?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
anyhow::bail!("git worktree list failed: {stderr}");
}
let stdout = String::from_utf8_lossy(&output.stdout);
let current_dir = std::env::current_dir().ok();
let is_interactive = std::io::stdout().is_terminal();
if is_interactive {
let entries = parse_worktree_entries(&stdout, current_dir.as_deref());
let commit_times: Vec<Option<DateTime<Utc>>> = entries
.iter()
.map(|entry| get_last_commit_time(&std::path::PathBuf::from(&entry.path)))
.collect();
let lines = format_worktree_table(&entries, &commit_times, show_path, color_mode);
for line in lines {
eprintln!("{line}");
}
} else {
if show_path {
let entries = parse_worktree_entries(&stdout, current_dir.as_deref());
let commit_times: Vec<Option<DateTime<Utc>>> = entries
.iter()
.map(|entry| get_last_commit_time(&std::path::PathBuf::from(&entry.path)))
.collect();
let lines = format_worktree_table(&entries, &commit_times, show_path, color_mode);
for line in lines {
println!("{line}");
}
} else {
let entries = parse_simple_worktree_entries(&stdout);
for (index, entry) in entries.iter().enumerate() {
if index == 0 {
println!("@");
} else if let Some(branch) = &entry.branch {
println!("{branch}");
} else {
println!("{}", display_path(&PathBuf::from(&entry.path)));
}
}
}
}
Ok(())
}