|
1 | 1 | use but_settings::AppSettings;
|
2 | 2 | use colored::Colorize;
|
3 | 3 | use gitbutler_branch::BranchCreateRequest;
|
4 |
| -use gitbutler_branch_actions::{create_virtual_branch, create_virtual_branch_from_branch, unapply_stack}; |
| 4 | +use gitbutler_branch_actions::{create_virtual_branch, unapply_stack}; |
5 | 5 | use gitbutler_command_context::CommandContext;
|
| 6 | +use gitbutler_oxidize::{ObjectIdExt, RepoExt}; |
6 | 7 | use gitbutler_project::Project;
|
7 |
| -use gitbutler_reference::Refname; |
8 | 8 | use gitbutler_stack::VirtualBranchesHandle;
|
9 | 9 | use std::path::Path;
|
10 |
| -use std::str::FromStr; |
11 | 10 |
|
12 | 11 | use crate::id::CliId;
|
13 | 12 |
|
@@ -69,18 +68,61 @@ pub(crate) fn create_branch(
|
69 | 68 | id_str.blue().underline()
|
70 | 69 | );
|
71 | 70 |
|
72 |
| - // Create a Refname from the branch name |
73 |
| - let branch_ref = Refname::from_str(&format!("refs/heads/{}", target_branch_name))?; |
74 |
| - |
75 |
| - let new_stack_id = create_virtual_branch_from_branch(&ctx, &branch_ref, None, None)?; |
76 |
| - |
77 |
| - // Update the branch name if it's different |
78 |
| - if branch_name != target_branch_name { |
79 |
| - let vb_state = VirtualBranchesHandle::new(ctx.project().gb_dir()); |
80 |
| - let mut stack = vb_state.get_stack(new_stack_id)?; |
81 |
| - stack.name = branch_name.to_string(); |
82 |
| - vb_state.set_stack(stack)?; |
| 71 | + // Find the target stack and get its current head commit |
| 72 | + let stacks = crate::log::stacks(&ctx)?; |
| 73 | + let target_stack = stacks.iter().find(|s| { |
| 74 | + s.heads.iter().any(|head| head.name.to_string() == target_branch_name) |
| 75 | + }); |
| 76 | + |
| 77 | + let target_stack = match target_stack { |
| 78 | + Some(s) => s, |
| 79 | + None => return Err(anyhow::anyhow!("No stack found for branch '{}'", target_branch_name)), |
| 80 | + }; |
| 81 | + |
| 82 | + let target_stack_id = target_stack.id.ok_or_else(|| anyhow::anyhow!("Target stack has no ID"))?; |
| 83 | + |
| 84 | + // Get the stack details to find the head commit |
| 85 | + let target_stack_details = crate::log::stack_details(&ctx, target_stack_id)?; |
| 86 | + if target_stack_details.branch_details.is_empty() { |
| 87 | + return Err(anyhow::anyhow!("Target stack has no branch details")); |
83 | 88 | }
|
| 89 | + |
| 90 | + // Find the target branch in the stack details |
| 91 | + let target_branch_details = target_stack_details.branch_details.iter().find(|b| |
| 92 | + b.name == target_branch_name |
| 93 | + ).ok_or_else(|| anyhow::anyhow!("Target branch '{}' not found in stack details", target_branch_name))?; |
| 94 | + |
| 95 | + // Get the head commit of the target branch |
| 96 | + let target_head_oid = if !target_branch_details.commits.is_empty() { |
| 97 | + // Use the last local commit |
| 98 | + target_branch_details.commits.last().unwrap().id |
| 99 | + } else if !target_branch_details.upstream_commits.is_empty() { |
| 100 | + // If no local commits, use the last upstream commit |
| 101 | + target_branch_details.upstream_commits.last().unwrap().id |
| 102 | + } else { |
| 103 | + return Err(anyhow::anyhow!("Target branch '{}' has no commits", target_branch_name)); |
| 104 | + }; |
| 105 | + |
| 106 | + // Create a new virtual branch |
| 107 | + let mut guard = project.exclusive_worktree_access(); |
| 108 | + let create_request = BranchCreateRequest { |
| 109 | + name: Some(branch_name.to_string()), |
| 110 | + ownership: None, |
| 111 | + order: None, |
| 112 | + selected_for_changes: None, |
| 113 | + }; |
| 114 | + |
| 115 | + let new_stack_id = create_virtual_branch(&ctx, &create_request, guard.write_permission())?; |
| 116 | + |
| 117 | + // Now set up the new branch to start from the target branch's head |
| 118 | + let vb_state = VirtualBranchesHandle::new(ctx.project().gb_dir()); |
| 119 | + let mut new_stack = vb_state.get_stack(new_stack_id.id)?; |
| 120 | + |
| 121 | + // Set the head of the new stack to be the target branch's head |
| 122 | + // This creates the stacking relationship |
| 123 | + let gix_repo = ctx.repo().to_gix()?; |
| 124 | + new_stack.set_stack_head(&vb_state, &gix_repo, target_head_oid.to_git2(), None)?; |
| 125 | + vb_state.set_stack(new_stack)?; |
84 | 126 |
|
85 | 127 | println!(
|
86 | 128 | "{} Stacked branch '{}' created successfully!",
|
|
0 commit comments