summaryrefslogtreecommitdiff
path: root/makima/src/daemon/worktree/manager.rs
diff options
context:
space:
mode:
Diffstat (limited to 'makima/src/daemon/worktree/manager.rs')
-rw-r--r--makima/src/daemon/worktree/manager.rs79
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,