diff options
Diffstat (limited to 'makima/src/daemon/worktree/manager.rs')
| -rw-r--r-- | makima/src/daemon/worktree/manager.rs | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/makima/src/daemon/worktree/manager.rs b/makima/src/daemon/worktree/manager.rs index 20c93b1..04180b8 100644 --- a/makima/src/daemon/worktree/manager.rs +++ b/makima/src/daemon/worktree/manager.rs @@ -692,6 +692,85 @@ impl WorktreeManager { }) } + /// Find and create a worktree from a previously pushed branch for a task. + /// + /// Searches local and remote branches for ones matching the task's UUID, + /// then creates a new worktree based on that branch. + pub async fn create_worktree_from_task_branch( + &self, + source_repo: &Path, + from_task_id: Uuid, + new_task_id: Uuid, + new_task_name: &str, + ) -> Result<WorktreeInfo, WorktreeError> { + let from_short_id = short_uuid(from_task_id); + let from_full_id = from_task_id.to_string(); + + tracing::info!( + from_task_id = %from_task_id, + new_task_id = %new_task_id, + "Searching for pushed branch to continue from" + ); + + // Fetch latest from remote first + let _ = Command::new("git") + .args(["fetch", "--all", "--prune"]) + .current_dir(source_repo) + .output() + .await; + + // Search for branches matching the task ID (both local and remote) + let output = Command::new("git") + .args(["branch", "-a", "--format=%(refname:short)"]) + .current_dir(source_repo) + .output() + .await?; + + if !output.status.success() { + return Err(WorktreeError::GitCommand( + "Failed to list branches".to_string(), + )); + } + + let branches_output = String::from_utf8_lossy(&output.stdout); + let mut found_branch: Option<String> = None; + + for line in branches_output.lines() { + let b = line.trim(); + if b.is_empty() { + continue; + } + // Match branches containing the full UUID or short UUID + if b.contains(&from_full_id) || b.contains(&from_short_id) { + // Prefer local branches, but accept remote + if let Some(remote_branch) = b.strip_prefix("origin/") { + if found_branch.is_none() { + found_branch = Some(remote_branch.to_string()); + } + } else { + found_branch = Some(b.to_string()); + } + } + } + + let from_branch = found_branch.ok_or_else(|| { + WorktreeError::GitCommand(format!( + "No branch found for task {} in repository", + from_short_id + )) + })?; + + tracing::info!( + from_task_id = %from_task_id, + from_branch = %from_branch, + "Found pushed branch, creating worktree from it" + ); + + // Create a worktree using the found branch as the base + self.create_worktree(source_repo, new_task_id, new_task_name, &from_branch) + .await + } + /// Remove a worktree and optionally its branch. pub async fn remove_worktree( &self, |
