Skip to main content

git_claw/workflow/
list.rs

1//! Active worktree slots listing and dashboard rendering.
2
3use crate::cli::output::{print_worktree_table, WorktreeRow};
4use crate::core::config::Config;
5use crate::core::port::calculate_effective_ports;
6use crate::infra::git::{
7    git_head_commit, resolve_git_common_dir, resolve_repo_name, resolve_toplevel,
8};
9use crate::infra::lock::SlotLock;
10use crate::infra::registry::SlotRegistry;
11use crate::workflow::error::WorkflowError;
12use std::path::Path;
13
14/// Inspects active worktree slots, runs auto-GC, and renders the status dashboard table.
15pub fn list_worktrees(repo_root: Option<&Path>) -> Result<(), WorkflowError> {
16    let toplevel = resolve_toplevel(repo_root)?;
17    let common_dir = resolve_git_common_dir(Some(&toplevel))?;
18    let repo_name = resolve_repo_name(&toplevel);
19
20    let config_path = toplevel.join(".git-claw.toml");
21    let config = Config::load_or_default(&config_path, &repo_name)?;
22
23    let registry_path = common_dir.join("claw/slots.json");
24    let lock_path = common_dir.join("claw/slots.lock");
25
26    let _lock = SlotLock::acquire(&lock_path)?;
27    let mut registry = SlotRegistry::load_or_empty(&registry_path)?;
28
29    // Pre-flight auto-GC of stale/orphaned worktree entries
30    let _ = registry.auto_gc(&registry_path, Some(&toplevel), true);
31
32    let mut rows = Vec::new();
33    for slot in &registry.slots {
34        let ports_map = calculate_effective_ports(&config.ports, slot.id)?;
35        let ports_str = if ports_map.is_empty() {
36            "-".to_string()
37        } else {
38            ports_map
39                .into_iter()
40                .map(|(name, port)| format!("{}:{}", name, port))
41                .collect::<Vec<_>>()
42                .join(", ")
43        };
44
45        let commit_str = git_head_commit(Path::new(&slot.path)).unwrap_or_else(|_| "-".to_string());
46
47        rows.push(WorktreeRow {
48            slot: slot.id,
49            branch: slot.branch.clone(),
50            path: slot.path.clone(),
51            ports: ports_str,
52            commit: commit_str,
53        });
54    }
55
56    drop(_lock);
57
58    print_worktree_table(&rows);
59
60    Ok(())
61}