Skip to content

Commit c0ac005

Browse files
authored
Merge pull request #10606 from Byron/next
v3 apply/unapply: MVP
2 parents b4ead2f + 00bae12 commit c0ac005

File tree

6 files changed

+656
-59
lines changed

6 files changed

+656
-59
lines changed

crates/but-core/src/ref_metadata.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,20 +60,21 @@ impl Workspace {
6060

6161
/// Insert `branch` as new stack if it's not yet contained in the workspace and if `order` is not `None` or push
6262
/// it to the end of the stack list.
63-
/// If a new stack is created, it's considered to be *in* the workspace. If there is an existing stack, it will
64-
/// also be put *in* the workspace as a side effect.
63+
/// If a new stack is created, it's considered to be *in* the workspace. If there is an existing stack, it
64+
/// may also be marked as *outside the workspace*, we do not change this.
6565
/// Note that `order` is only relevant at insertion time, not if the branch already exists.
66-
/// Returns `true` if the ref was newly added, or `false` if it already existed.
66+
/// Returns `(stack_id, segment_idx)` of the stack that was either newly created, or already present.
67+
/// Note that `segment_idx` may be non-0 if `branch` already existed as segment, and the caller has to
68+
/// deal with this.
6769
pub fn add_or_insert_new_stack_if_not_present(
6870
&mut self,
6971
branch: &FullNameRef,
7072
order: Option<usize>,
71-
) -> bool {
72-
if let Some((stack_idx, _)) =
73+
) -> (usize, usize) {
74+
if let Some(owners) =
7375
self.find_owner_indexes_by_name(branch, StackKind::AppliedAndUnapplied)
7476
{
75-
self.stacks[stack_idx].in_workspace = true;
76-
return false;
77+
return owners;
7778
};
7879

7980
let stack = WorkspaceStack {
@@ -84,15 +85,18 @@ impl Workspace {
8485
archived: false,
8586
}],
8687
};
87-
match order.map(|idx| idx.min(self.stacks.len())) {
88+
let stack_idx = match order.map(|idx| idx.min(self.stacks.len())) {
8889
None => {
90+
let idx = self.stacks.len();
8991
self.stacks.push(stack);
92+
idx
9093
}
9194
Some(existing_index) => {
9295
self.stacks.insert(existing_index, stack);
96+
existing_index
9397
}
94-
}
95-
true
98+
};
99+
(stack_idx, 0)
96100
}
97101

98102
/// Insert `branch` as new segment if it's not yet contained in the workspace,

crates/but-core/tests/core/ref_metadata.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,31 @@ mod workspace {
88
assert_eq!(ws.stacks.len(), 0);
99

1010
let a_ref = r("refs/heads/A");
11-
assert!(ws.add_or_insert_new_stack_if_not_present(a_ref, Some(100)));
12-
assert!(!ws.add_or_insert_new_stack_if_not_present(a_ref, Some(200)));
11+
assert_eq!(
12+
ws.add_or_insert_new_stack_if_not_present(a_ref, Some(100)),
13+
(0, 0)
14+
);
15+
assert_eq!(
16+
ws.add_or_insert_new_stack_if_not_present(a_ref, Some(200)),
17+
(0, 0)
18+
);
1319
assert_eq!(ws.stacks.len(), 1);
1420

1521
let b_ref = r("refs/heads/B");
16-
assert!(ws.add_or_insert_new_stack_if_not_present(b_ref, Some(0)));
22+
assert_eq!(
23+
ws.add_or_insert_new_stack_if_not_present(b_ref, Some(0)),
24+
(0, 0)
25+
);
1726
assert_eq!(
1827
ws.stack_names(AppliedAndUnapplied).collect::<Vec<_>>(),
1928
[b_ref, a_ref]
2029
);
2130

2231
let c_ref = r("refs/heads/C");
23-
assert!(ws.add_or_insert_new_stack_if_not_present(c_ref, None));
32+
assert_eq!(
33+
ws.add_or_insert_new_stack_if_not_present(c_ref, None),
34+
(2, 0)
35+
);
2436
assert_eq!(
2537
ws.stack_names(AppliedAndUnapplied).collect::<Vec<_>>(),
2638
[b_ref, a_ref, c_ref]
@@ -55,7 +67,10 @@ mod workspace {
5567
None,
5668
"anchor doesn't exist"
5769
);
58-
assert!(ws.add_or_insert_new_stack_if_not_present(a_ref, None));
70+
assert_eq!(
71+
ws.add_or_insert_new_stack_if_not_present(a_ref, None),
72+
(0, 0)
73+
);
5974
assert_eq!(
6075
ws.insert_new_segment_above_anchor_if_not_present(b_ref, a_ref),
6176
Some(true),
@@ -73,6 +88,12 @@ mod workspace {
7388
Some(true)
7489
);
7590

91+
assert_eq!(
92+
ws.add_or_insert_new_stack_if_not_present(a_ref, None),
93+
(0, 2),
94+
"adding a new stack can 'fail' if the segment is already present, but not as stack tip"
95+
);
96+
7697
insta::assert_snapshot!(but_testsupport::sanitize_uuids_and_timestamps(format!("{ws:#?}")), @r#"
7798
Workspace {
7899
ref_info: RefInfo { created_at: None, updated_at: None },

crates/but-graph/src/ref_metadata_legacy.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,13 +220,20 @@ impl RefMetadata for VirtualBranchesTomlMetadata {
220220
}
221221

222222
fn branch(&self, ref_name: &FullNameRef) -> anyhow::Result<Self::Handle<Branch>> {
223-
let Some((stack, branch)) = self.data().branches.values().find_map(|stack| {
224-
stack.heads.iter().find_map(|branch| {
225-
full_branch_name(branch.name.as_str()).and_then(|full_name| {
226-
(full_name.as_ref() == ref_name).then_some((stack, branch))
223+
let Some((stack, branch)) = self
224+
.data()
225+
.branches
226+
.values()
227+
// There shouldn't be duplication, but let's be sure it's deterministic if it is.
228+
.sorted_by_key(|s| s.order)
229+
.find_map(|stack| {
230+
stack.heads.iter().find_map(|branch| {
231+
full_branch_name(branch.name.as_str()).and_then(|full_name| {
232+
(full_name.as_ref() == ref_name).then_some((stack, branch))
233+
})
227234
})
228235
})
229-
}) else {
236+
else {
230237
return Ok(VBTomlMetadataHandle {
231238
is_default: true,
232239
ref_name: ref_name.to_owned(),
@@ -373,6 +380,12 @@ impl RefMetadata for VirtualBranchesTomlMetadata {
373380
vb_stack.heads.reverse()
374381
}
375382

383+
for (stack_idx, stack) in value.stacks.iter().enumerate() {
384+
if let Some(vb_stack) = self.data_mut().branches.get_mut(&stack.id) {
385+
vb_stack.order = stack_idx;
386+
}
387+
}
388+
376389
let stacks_to_delete: Vec<_> = self
377390
.data()
378391
.branches

0 commit comments

Comments
 (0)