Skip to content

Commit 7ab5b44

Browse files
authored
Merge pull request #10991 from gitbutlerapp/conflicted-short-names
Also provide the names of the stacks that conflicted, so they can be shown.
2 parents 6b22b0c + fe9f5fc commit 7ab5b44

File tree

7 files changed

+75
-17
lines changed

7 files changed

+75
-17
lines changed

apps/desktop/cypress/e2e/support/mock/backend.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ export default class MockBackend {
623623

624624
// Do nothing for now
625625
return {
626+
unappliedStacksShortNames: [],
626627
stackId: 'something',
627628
unappliedStacks: []
628629
};

apps/desktop/src/lib/stacks/stack.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,43 @@ import type iconsJson from '@gitbutler/ui/data/icons.json';
77
export type CreateBranchFromBranchOutcome = {
88
stackId: string;
99
unappliedStacks: string[];
10+
unappliedStacksShortNames: string[];
1011
};
1112

13+
function stackCount(numStacks: number): string {
14+
if (numStacks === 1) {
15+
return 'one stack';
16+
} else {
17+
return 'some stacks';
18+
}
19+
}
20+
21+
function prettyNamedListIfPossible(expectedNames: number, names: string[]): string {
22+
// It could happen that not all stacks had names, for now we don't deal with that.
23+
// Also, the old codepath doesn't produce names.
24+
if (expectedNames !== names.length) {
25+
return stackCount(expectedNames);
26+
}
27+
if (names.length === 0) {
28+
return '';
29+
} else if (names.length === 1) {
30+
return `stack ${names[0]}`;
31+
} else if (names.length === 2) {
32+
return `stack ${names[0]} and stack ${names[1]}`;
33+
}
34+
35+
const allButLast = names.slice(0, -1);
36+
const last = names[names.length - 1];
37+
38+
return `${allButLast.map((n) => `stack ${n}`).join(', ')}, and stack ${last}`;
39+
}
40+
1241
export function handleCreateBranchFromBranchOutcome(outcome: CreateBranchFromBranchOutcome) {
1342
if (outcome.unappliedStacks.length > 0) {
1443
showToast({
1544
testId: TestId.StacksUnappliedToast,
16-
title: 'Heads up: We had to unapply some stacks to apply this one',
17-
message: `There were some conflicts detected when applying this branch into your workspace, so we automatically unapplied ${outcome.unappliedStacks.length} ${outcome.unappliedStacks.length === 1 ? 'stack' : 'stacks'}.
45+
title: `Heads up: We had to unapply ${stackCount(outcome.unappliedStacks.length)} to apply this one`,
46+
message: `There were some conflicts detected when applying this branch into your workspace, so we automatically unapplied ${prettyNamedListIfPossible(outcome.unappliedStacks.length, outcome.unappliedStacksShortNames)}.
1847
You can always re-apply them later from the branches page.`
1948
});
2049
}

crates/but-testing/src/command/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ pub mod stacks {
282282
let ref_name = Refname::from_str(&format!("refs/remotes/{remote_name}/{name}"))?;
283283
let remote_ref_name = RemoteRefname::new(remote_name, name);
284284

285-
let (stack_id, _) = gitbutler_branch_actions::create_virtual_branch_from_branch(
285+
let (stack_id, _, _) = gitbutler_branch_actions::create_virtual_branch_from_branch(
286286
ctx,
287287
&ref_name,
288288
Some(remote_ref_name),

crates/but-tools/src/workspace.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1410,7 +1410,7 @@ pub fn split_branch(
14101410
let refname = Refname::Local(LocalRefname::new(&params.new_branch_name, None));
14111411
let branch_manager = ctx.branch_manager();
14121412

1413-
let (stack_id, _) = branch_manager.create_virtual_branch_from_branch(
1413+
let (stack_id, _, _) = branch_manager.create_virtual_branch_from_branch(
14141414
&refname,
14151415
None,
14161416
None,

crates/gitbutler-branch-actions/src/actions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ pub fn create_virtual_branch_from_branch(
516516
branch: &Refname,
517517
remote: Option<RemoteRefname>,
518518
pr_number: Option<usize>,
519-
) -> Result<(StackId, Vec<StackId>)> {
519+
) -> Result<(StackId, Vec<StackId>, Vec<String>)> {
520520
let mut guard = ctx.project().exclusive_worktree_access();
521521
ctx.verify(guard.write_permission())?;
522522
ensure_open_workspace_mode(ctx)

crates/gitbutler-branch-actions/src/branch_manager/branch_creation.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,21 @@ use crate::{
3434
pub struct CreateBranchFromBranchOutcome {
3535
pub stack_id: StackId,
3636
pub unapplied_stacks: Vec<StackId>,
37+
pub unapplied_stacks_short_names: Vec<String>,
3738
}
3839

39-
impl From<(StackId, Vec<StackId>)> for CreateBranchFromBranchOutcome {
40-
fn from((stack_id, unapplied_stacks): (StackId, Vec<StackId>)) -> Self {
40+
impl From<(StackId, Vec<StackId>, Vec<String>)> for CreateBranchFromBranchOutcome {
41+
fn from(
42+
(stack_id, unapplied_stacks, unapplied_stacks_short_names): (
43+
StackId,
44+
Vec<StackId>,
45+
Vec<String>,
46+
),
47+
) -> Self {
4148
Self {
4249
stack_id,
4350
unapplied_stacks,
51+
unapplied_stacks_short_names,
4452
}
4553
}
4654
}
@@ -145,7 +153,7 @@ impl BranchManager<'_> {
145153
upstream_branch: Option<RemoteRefname>,
146154
pr_number: Option<usize>,
147155
perm: &mut WorktreeWritePermission,
148-
) -> Result<(StackId, Vec<StackId>)> {
156+
) -> Result<(StackId, Vec<StackId>, Vec<String>)> {
149157
let branch_name = target
150158
.branch()
151159
.expect("always a branch reference")
@@ -183,7 +191,26 @@ impl BranchManager<'_> {
183191
.0
184192
.id
185193
.context("BUG: newly applied stacks should always have a stack id")?;
186-
return Ok((applied_branch_stack_id, out.conflicting_stack_ids));
194+
let conflicted_stack_short_names_for_display = ws
195+
.metadata
196+
.as_ref()
197+
.map(|md| {
198+
md.stacks
199+
.iter()
200+
.filter_map(|s| {
201+
out.conflicting_stack_ids
202+
.contains(&s.id)
203+
.then(|| s.ref_name().map(|rn| rn.shorten().to_string()))
204+
.flatten()
205+
})
206+
.collect::<Vec<_>>()
207+
})
208+
.unwrap_or_default();
209+
return Ok((
210+
applied_branch_stack_id,
211+
out.conflicting_stack_ids,
212+
conflicted_stack_short_names_for_display,
213+
));
187214
}
188215
let old_cwd = (!self.ctx.app_settings().feature_flags.cv3)
189216
.then(|| self.ctx.repo().create_wd_tree(0).map(|tree| tree.id()))
@@ -312,14 +339,14 @@ impl BranchManager<'_> {
312339
self.ctx.add_branch_reference(&branch)?;
313340

314341
match self.apply_branch(branch.id, perm, old_workspace, old_cwd) {
315-
Ok((_, unapplied_stacks)) => Ok((branch.id, unapplied_stacks)),
342+
Ok((_, unapplied_stacks)) => Ok((branch.id, unapplied_stacks, vec![])),
316343
Err(err)
317344
if err
318345
.downcast_ref()
319346
.is_some_and(|marker: &Marker| *marker == Marker::ProjectConflict) =>
320347
{
321348
// if branch conflicts with the workspace, it's ok. keep it unapplied
322-
Ok((branch.id, vec![]))
349+
Ok((branch.id, vec![], vec![]))
323350
}
324351
Err(err) => Err(err).context("failed to apply"),
325352
}

crates/gitbutler-branch-actions/src/move_branch.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,13 @@ pub(crate) fn tear_off_branch(
133133
.context("failed to update gitbutler workspace")?;
134134

135135
let branch_manager = ctx.branch_manager();
136-
let (_, unapplied_stacks) = branch_manager.create_virtual_branch_from_branch(
137-
&Refname::Local(LocalRefname::new(subject_branch_name, None)),
138-
None,
139-
None,
140-
perm,
141-
)?;
136+
let (_, unapplied_stacks, _unapplied_stack_shortnames) = branch_manager
137+
.create_virtual_branch_from_branch(
138+
&Refname::Local(LocalRefname::new(subject_branch_name, None)),
139+
None,
140+
None,
141+
perm,
142+
)?;
142143

143144
Ok(MoveBranchResult {
144145
deleted_stacks,

0 commit comments

Comments
 (0)