use anyhow::Result;
use std::path::PathBuf;
use crate::workspace::WorkspaceManager;
use crate::worktree::config::WorktreeConfig;
use crate::worktree::config_manager::{
ConfigSummary, ConfigValidationError, WorktreeConfigManager,
};
use crate::worktree::operations::{CreateOptions, RemoveOptions, WorktreeOperations};
use crate::worktree::status::WorktreeInfo;
pub struct WorktreeManager {
operations: WorktreeOperations,
pub workspace_root: PathBuf,
config: WorktreeConfig,
config_manager: Option<WorktreeConfigManager>,
}
impl WorktreeManager {
pub async fn new(workspace_root: PathBuf, config: Option<WorktreeConfig>) -> Result<Self> {
let config =
config.unwrap_or_else(|| WorktreeConfig::load_with_overrides().unwrap_or_default());
config
.validate()
.map_err(|e| anyhow::anyhow!("Invalid config: {}", e))?;
let repo_name = workspace_root
.file_name()
.and_then(|n| n.to_str())
.map(|s| s.to_string());
let operations = if let Some(name) = repo_name {
WorktreeOperations::new_with_repo_name(workspace_root.clone(), config.clone(), name)
} else {
WorktreeOperations::new(workspace_root.clone(), config.clone())
};
Ok(Self {
operations,
workspace_root,
config,
config_manager: None,
})
}
pub async fn new_with_workspace_manager(
workspace_manager: &WorkspaceManager,
repo_path: Option<PathBuf>,
) -> Result<Self> {
let config_manager =
WorktreeConfigManager::new(workspace_manager.get_config_path().clone());
config_manager.migrate_legacy_config().await?;
let repo_name = repo_path
.as_ref()
.and_then(|p| p.file_name())
.and_then(|n| n.to_str())
.map(|s| s.to_string());
let config = if let Some(ref path) = repo_path {
config_manager.load_config_for_repo(path).await?
} else {
WorktreeConfig::load_with_overrides()
.map_err(|e| anyhow::anyhow!("Failed to load config: {}", e))?
};
let repo_root = repo_path
.as_ref()
.unwrap_or(workspace_manager.get_workspace_root())
.clone();
let operations = if let Some(name) = repo_name {
WorktreeOperations::new_with_repo_name(repo_root.clone(), config.clone(), name)
} else {
WorktreeOperations::new(repo_root.clone(), config.clone())
};
Ok(Self {
operations,
workspace_root: repo_root,
config,
config_manager: Some(config_manager),
})
}
pub async fn create_worktree(&self, task_id: String) -> Result<WorktreeInfo> {
let options = CreateOptions {
task_id,
base_branch: None,
force: false,
custom_path: None,
};
self.operations.create_worktree(options).await
}
pub async fn create_worktree_with_options(
&self,
options: CreateOptions,
) -> Result<WorktreeInfo> {
self.operations.create_worktree(options).await
}
pub async fn remove_worktree(&self, branch_or_path: String, force: bool) -> Result<()> {
let options = RemoveOptions {
target: branch_or_path,
force,
delete_branch: false,
};
self.operations.remove_worktree(options).await
}
pub async fn remove_worktree_with_options(&self, options: RemoveOptions) -> Result<()> {
self.operations.remove_worktree(options).await
}
pub async fn list_worktrees(&self) -> Result<Vec<WorktreeInfo>> {
self.operations.list_worktrees().await
}
pub async fn get_git_root(&self) -> Result<PathBuf> {
self.operations.find_git_root().await
}
pub fn get_config(&self) -> &WorktreeConfig {
&self.config
}
pub async fn resolve_worktree_target(&self, target: &str) -> Result<WorktreeInfo> {
self.operations.resolve_worktree_target(target).await
}
pub fn get_operations(&self) -> WorktreeOperations {
self.operations.clone()
}
pub async fn get_config_summary(&self) -> Result<ConfigSummary> {
if let Some(config_manager) = &self.config_manager {
config_manager.get_config_summary().await
} else {
Err(anyhow::anyhow!("Config manager not available"))
}
}
pub async fn validate_configuration(&self) -> Result<Vec<ConfigValidationError>> {
if let Some(config_manager) = &self.config_manager {
config_manager.validate_all_configs().await
} else {
Ok(Vec::new())
}
}
}