feat(api): add optional order parameter to branch creation#12693
feat(api): add optional order parameter to branch creation#12693PavelLaptev wants to merge 2 commits intomasterfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
There was a problem hiding this comment.
Pull request overview
This PR extends the virtual-branch creation-from-branch API surface to accept an optional order parameter so callers can control where the resulting stack is placed in the workspace ordering (e.g., “leftmost”).
Changes:
- Add an optional
order: Option<usize>/order?: numberparameter tocreate_virtual_branch_from_branchacross Rust API layers and the desktop backend client. - Propagate the new parameter through CLI/tools/tests call sites (passing
Nonewhere unused). - Desktop UI now optionally sends
order: 0(leftmost) based on the persisted “branch-placement-leftmost” preference.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/gitbutler-cli/src/command/vbranch.rs | Update call site to pass new order argument (None). |
| crates/gitbutler-branch-actions/tests/virtual_branches/create_virtual_branch_from_branch.rs | Update tests to match new function signature (adds None). |
| crates/gitbutler-branch-actions/tests/virtual_branches/apply_virtual_branch.rs | Update test call site to pass new order argument (None). |
| crates/gitbutler-branch-actions/src/move_branch.rs | Update internal call site to pass new order argument (None). |
| crates/gitbutler-branch-actions/src/branch_manager/branch_creation.rs | Add order parameter and incorporate it into stack creation ordering logic. |
| crates/gitbutler-branch-actions/src/actions.rs | Thread order through the public action API. |
| crates/but/src/command/legacy/branch/apply.rs | Update legacy CLI path call sites to pass order (None). |
| crates/but-tools/src/workspace.rs | Update workspace helper call site to pass order (None). |
| crates/but-testing/src/command/mod.rs | Update test CLI helper call site to pass order (None). |
| crates/but-api/src/legacy/workspace.rs | Update legacy API workspace split call site to pass order (None). |
| crates/but-api/src/legacy/virtual_branches.rs | Expose order on legacy API function and forward it to branch-actions. |
| apps/desktop/src/lib/stacks/stackService.svelte.ts | Expand desktop backend API mutation args type to include order?: number. |
| apps/desktop/src/components/BranchesViewPR.svelte | Use persisted preference to optionally send order: 0 when applying a PR branch. |
| apps/desktop/src/components/BranchesView.svelte | Use persisted preference to optionally send order: 0 when checking out/applying a branch. |
Comments suppressed due to low confidence (1)
crates/gitbutler-branch-actions/src/branch_manager/branch_creation.rs:219
- In the non-apply3 code path,
orderis taken from the request (let order = order.unwrap_or(...)) and later written into the stack, but there’s no corresponding renumber/“make space” step for existing in-workspace stacks. If a caller passesSome(0)(the desktop UI now can), this can create duplicate/overlappingStack.ordervalues and leave ordering inconsistent.
Consider normalizing and shifting existing stacks when order is provided (similar to create_virtual_branch), or clamp/ignore order when apply3 is disabled so behavior is consistent across feature-flag states.
let order = order.unwrap_or(vb_state.next_order_index()?);
let mut branch = if let Some(mut branch) = vb_state
.find_by_top_reference_name_where_not_in_workspace(&target.to_string())?
.or(vb_state.find_by_source_refname_where_not_in_workspace(target)?)
| pub fn create_virtual_branch_from_branch( | ||
| &self, | ||
| target: &Refname, | ||
| upstream_branch: Option<RemoteRefname>, | ||
| pr_number: Option<usize>, | ||
| order: Option<usize>, | ||
| perm: &mut RepoExclusive, | ||
| ) -> Result<(StackId, Vec<StackId>, Vec<String>)> { |
There was a problem hiding this comment.
The new parameter order is later shadowed by a local binding (let order = order.unwrap_or(...)), which makes it harder to distinguish “requested order” vs “resolved order” when reading/debugging. Consider renaming either the parameter (e.g., requested_order) or the local value (e.g., resolved_order) to avoid shadowing.
| pr_number: Option<usize>, | ||
| order: Option<usize>, | ||
| perm: &mut RepoExclusive, | ||
| ) -> Result<(StackId, Vec<StackId>, Vec<String>)> { |
There was a problem hiding this comment.
The new order input isn’t covered by tests yet. It would be good to add a create_virtual_branch_from_branch(..., order: Some(0)) test (and possibly another non-zero case) asserting that the created stack ends up at the requested position and that existing stacks are shifted/renumbered appropriately.
There was a problem hiding this comment.
The shadowing is real. However, this is idiomatic Rust — shadowing an Option with its unwrapped value is a common and accepted pattern. It's not a bug or a readability problem in Rust conventions, unlike in other languages. The suggestion is a matter of style preference, not a correctness issue.
|
@Caleb-T-Owens, mind checking this one when you're free? Thanks! |
0d657a8 to
41e50fc
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
crates/gitbutler-branch-actions/src/branch_manager/branch_creation.rs:224
- When
orderis provided, this path setsbranch.order = order(or passesorderintoStack::new_from_existing) without making room by shifting existing stacks’ordervalues. This can create duplicateorderindices (e.g. inserting at0), breaking deterministic UI ordering. Consider normalizing ordering first (e.g.vb_state.update_ordering()), clampingorderto[0..=len], and shifting existing stacks’ orders (similar tocreate_virtual_branch) before assigning the new stack’s order.
let order = order.unwrap_or(vb_state.next_order_index()?);
let mut branch = if let Some(mut branch) = vb_state
.find_by_top_reference_name_where_not_in_workspace(&target.to_string())?
.or(vb_state.find_by_source_refname_where_not_in_workspace(target)?)
&& branch.is_initialized()
{
branch.upstream = upstream_branch; // Used as remote when listing commits.
branch.order = order;
branch.in_workspace = true;
| .context("failed to peel to commit")?; | ||
|
|
||
| let order = vb_state.next_order_index()?; | ||
| let order = order.unwrap_or(vb_state.next_order_index()?); | ||
|
|
There was a problem hiding this comment.
The new order: Option<usize> behavior for create_virtual_branch_from_branch isn’t currently exercised by tests (all updated call sites pass None). Please add at least one test that passes Some(0) and asserts the resulting stack ordering is correct (including any shifting/renumbering of existing stacks), so regressions in placement logic are caught.
41e50fc to
8663924
Compare
Addressing this issue https://discord.com/channels/1060193121130000425/1073202153163857920/1478838727085391953
cc @nshcr
This pull request introduces support for specifying the placement order when creating a virtual branch from an existing branch, allowing users to optionally add new branches to the leftmost position in the UI. The change propagates a new
orderparameter through the frontend, API, and backend, and updates all relevant function signatures and test cases to accommodate this new functionality.Frontend enhancements:
addToLeftmost) in bothBranchesView.svelteandBranchesViewPR.svelteto allow users to choose whether new branches are added to the leftmost position. When enabled, theorderparameter is set to0when creating a branch. [1] [2] [3] [4]API and backend changes:
createVirtualBranchFromBranchmutation and all related Rust function signatures to accept an optionalorderparameter, ensuring the order is applied when creating the branch. [1] [2] [3] [4]orderif specified, or fall back to the default ordering logic. [1] [2] [3]Test and CLI updates:
orderparameter, ensuring compatibility and correctness throughout the codebase. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17]