vibe_workspace/worktree/
manager.rs1use anyhow::Result;
4use std::path::PathBuf;
5
6use crate::workspace::WorkspaceManager;
7use crate::worktree::config::WorktreeConfig;
8use crate::worktree::config_manager::{
9 ConfigSummary, ConfigValidationError, WorktreeConfigManager,
10};
11use crate::worktree::operations::{CreateOptions, RemoveOptions, WorktreeOperations};
12use crate::worktree::status::WorktreeInfo;
13
14pub struct WorktreeManager {
16 operations: WorktreeOperations,
17 pub workspace_root: PathBuf,
18 config: WorktreeConfig,
19 config_manager: Option<WorktreeConfigManager>,
20}
21
22impl WorktreeManager {
23 pub async fn new(workspace_root: PathBuf, config: Option<WorktreeConfig>) -> Result<Self> {
25 let config =
26 config.unwrap_or_else(|| WorktreeConfig::load_with_overrides().unwrap_or_default());
27
28 config
29 .validate()
30 .map_err(|e| anyhow::anyhow!("Invalid config: {}", e))?;
31
32 let repo_name = workspace_root
34 .file_name()
35 .and_then(|n| n.to_str())
36 .map(|s| s.to_string());
37
38 let operations = if let Some(name) = repo_name {
39 WorktreeOperations::new_with_repo_name(workspace_root.clone(), config.clone(), name)
40 } else {
41 WorktreeOperations::new(workspace_root.clone(), config.clone())
42 };
43
44 Ok(Self {
45 operations,
46 workspace_root,
47 config,
48 config_manager: None,
49 })
50 }
51
52 pub async fn new_with_workspace_manager(
54 workspace_manager: &WorkspaceManager,
55 repo_path: Option<PathBuf>,
56 ) -> Result<Self> {
57 let config_manager =
58 WorktreeConfigManager::new(workspace_manager.get_config_path().clone());
59
60 config_manager.migrate_legacy_config().await?;
62
63 let repo_name = repo_path
65 .as_ref()
66 .and_then(|p| p.file_name())
67 .and_then(|n| n.to_str())
68 .map(|s| s.to_string());
69
70 let config = if let Some(ref path) = repo_path {
72 config_manager.load_config_for_repo(path).await?
73 } else {
74 WorktreeConfig::load_with_overrides()
75 .map_err(|e| anyhow::anyhow!("Failed to load config: {}", e))?
76 };
77
78 let repo_root = repo_path
80 .as_ref()
81 .unwrap_or(workspace_manager.get_workspace_root())
82 .clone();
83
84 let operations = if let Some(name) = repo_name {
85 WorktreeOperations::new_with_repo_name(repo_root.clone(), config.clone(), name)
86 } else {
87 WorktreeOperations::new(repo_root.clone(), config.clone())
88 };
89
90 Ok(Self {
91 operations,
92 workspace_root: repo_root,
93 config,
94 config_manager: Some(config_manager),
95 })
96 }
97
98 pub async fn create_worktree(&self, task_id: String) -> Result<WorktreeInfo> {
100 let options = CreateOptions {
101 task_id,
102 base_branch: None,
103 force: false,
104 custom_path: None,
105 };
106
107 self.operations.create_worktree(options).await
108 }
109
110 pub async fn create_worktree_with_options(
112 &self,
113 options: CreateOptions,
114 ) -> Result<WorktreeInfo> {
115 self.operations.create_worktree(options).await
116 }
117
118 pub async fn remove_worktree(&self, branch_or_path: String, force: bool) -> Result<()> {
120 let options = RemoveOptions {
121 target: branch_or_path,
122 force,
123 delete_branch: false,
124 };
125
126 self.operations.remove_worktree(options).await
127 }
128
129 pub async fn remove_worktree_with_options(&self, options: RemoveOptions) -> Result<()> {
131 self.operations.remove_worktree(options).await
132 }
133
134 pub async fn list_worktrees(&self) -> Result<Vec<WorktreeInfo>> {
136 self.operations.list_worktrees().await
137 }
138
139 pub async fn get_git_root(&self) -> Result<PathBuf> {
141 self.operations.find_git_root().await
142 }
143
144 pub fn get_config(&self) -> &WorktreeConfig {
146 &self.config
147 }
148
149 pub async fn resolve_worktree_target(&self, target: &str) -> Result<WorktreeInfo> {
151 self.operations.resolve_worktree_target(target).await
152 }
153
154 pub fn get_operations(&self) -> WorktreeOperations {
156 self.operations.clone()
157 }
158
159 pub async fn get_config_summary(&self) -> Result<ConfigSummary> {
161 if let Some(config_manager) = &self.config_manager {
162 config_manager.get_config_summary().await
163 } else {
164 Err(anyhow::anyhow!("Config manager not available"))
165 }
166 }
167
168 pub async fn validate_configuration(&self) -> Result<Vec<ConfigValidationError>> {
170 if let Some(config_manager) = &self.config_manager {
171 config_manager.validate_all_configs().await
172 } else {
173 Ok(Vec::new())
174 }
175 }
176}