Skip to content

Commit 9684391

Browse files
authored
Merge pull request #8315 from Byron/ref-updates
Tame ref-updates
2 parents ea9e98c + 41ddded commit 9684391

File tree

32 files changed

+174
-161
lines changed

32 files changed

+174
-161
lines changed

crates/but-workspace/src/commit_engine/mod.rs

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -348,22 +348,57 @@ pub fn create_commit_and_update_refs(
348348
return Ok(out);
349349
};
350350

351-
let commit_to_find = match destination {
351+
let (commit_to_find, is_amend) = match destination {
352352
Destination::NewCommit {
353353
parent_commit_id, ..
354-
} => parent_commit_id,
355-
Destination::AmendCommit(commit) => Some(commit),
354+
} => (parent_commit_id, false),
355+
Destination::AmendCommit(commit) => (Some(commit), true),
356356
};
357357

358358
if let Some(commit_in_graph) = commit_to_find {
359359
let mut all_refs_by_id = gix::hashtable::HashMap::<_, Vec<_>>::default();
360-
for (commit_id, git_reference) in repo
361-
.references()?
362-
.prefixed("refs/heads/")?
363-
.chain(repo.references()?.prefixed("refs/gitbutler/")?)
364-
.filter_map(Result::ok)
365-
.filter_map(|r| r.try_id().map(|id| (id.detach(), r.inner.name)))
366-
{
360+
let mut checked_out_ref_name = None;
361+
let checked_out_ref = repo.head_ref()?.and_then(|mut r| {
362+
let id = r.peel_to_id_in_place().ok()?.detach();
363+
checked_out_ref_name = Some(r.inner.name.clone());
364+
Some((id, r.inner.name))
365+
});
366+
let (platform_storage, platform_storage_2);
367+
let checked_out_and_gitbutler_refs =
368+
checked_out_ref
369+
.into_iter()
370+
// TODO: remove this as `refs/gitbutler/` won't contain relevant refs anymore.
371+
.chain({
372+
platform_storage_2 = repo.references()?;
373+
platform_storage_2
374+
.prefixed("refs/gitbutler/")?
375+
.filter_map(Result::ok)
376+
.filter_map(|r| r.try_id().map(|id| (id.detach(), r.inner.name)))
377+
})
378+
.chain(
379+
// When amending, we want to update all branches that pointed to the old commit to now point to the new commit.
380+
if is_amend {
381+
Box::new({
382+
platform_storage = repo.references()?;
383+
platform_storage
384+
.prefixed("refs/heads/")?
385+
.filter_map(Result::ok)
386+
.filter_map(|r| {
387+
let is_checked_out = checked_out_ref_name.as_ref().is_some_and(
388+
|checked_out_ref| checked_out_ref == &r.inner.name,
389+
);
390+
if is_checked_out {
391+
None
392+
} else {
393+
r.try_id().map(|id| (id.detach(), r.inner.name))
394+
}
395+
})
396+
}) as Box<dyn Iterator<Item = _>>
397+
} else {
398+
Box::new(std::iter::empty())
399+
},
400+
);
401+
for (commit_id, git_reference) in checked_out_and_gitbutler_refs {
367402
all_refs_by_id
368403
.entry(commit_id)
369404
.or_default()
@@ -435,7 +470,7 @@ pub fn create_commit_and_update_refs(
435470
&& !wsc.inner.parents.contains(&branch_tip) /* the branch tip we know isn't yet merged */
436471
// but the tip is known to the workspace
437472
&& vb.branches.values().any(|s| {
438-
s.head(repo)
473+
s.head_oid(repo)
439474
.is_ok_and(|head_id| head_id == branch_tip)
440475
}) {
441476
let mut stacks: Vec<_> = vb

crates/but-workspace/src/commit_engine/reference_frame.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ impl ReferenceFrame {
4747
.context("Didn't find stack - was it deleted just now?")?;
4848
Ok(ReferenceFrame {
4949
workspace_tip: Some(head_id.detach()),
50-
branch_tip: Some(stack.head(repo)?),
50+
branch_tip: Some(stack.head_oid(repo)?),
5151
})
5252
}
5353
InferenceMode::CommitIdInStack(commit_id) => {
5454
for stack in vb.branches.values() {
55-
let stack_tip = stack.head(repo)?;
55+
let stack_tip = stack.head_oid(repo)?;
5656
if stack_tip
5757
.attach(repo)
5858
.ancestors()

crates/but-workspace/src/commit_engine/refs.rs

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,8 @@ pub fn rewrite(
3535
continue; // Dont rewrite refs for other stacks
3636
}
3737
}
38-
if stack.head(repo)? == old {
39-
// Perhaps skip this - the head will be updated later in this call
40-
// stack.set_stack_head_without_persisting(repo, new.to_git2(), None)?;
41-
// Does it make sense to set stack tree in v3? I think not
42-
// stack.tree = new
43-
// .attach(repo)
44-
// .object()?
45-
// .into_commit()
46-
// .tree_id()?
47-
// .to_git2();
38+
if stack.head_oid(repo)? == old {
39+
// The actual head will be updated later.
4840
updated_refs.push(UpdatedReference {
4941
old_commit_id: old,
5042
new_commit_id: new,
@@ -65,15 +57,16 @@ pub fn rewrite(
6557
});
6658
for (idx, branch) in stack.heads.iter_mut().rev().enumerate() {
6759
let id = branch.head_oid(repo)?;
68-
if id == old {
69-
if update_up_to_idx.is_some() && Some(idx) > update_up_to_idx {
70-
// Make sure the actual refs also don't update (later)
71-
already_updated_refs.push(format!("refs/heads/{}", branch.name()).into());
72-
continue;
73-
}
74-
if let Some(full_refname) = branch.set_head(new, repo)? {
75-
already_updated_refs.push(full_refname)
76-
}
60+
if id != old {
61+
continue;
62+
}
63+
if update_up_to_idx.is_some() && Some(idx) > update_up_to_idx {
64+
// Make sure the actual refs also don't update (later)
65+
already_updated_refs.push(format!("refs/heads/{}", branch.name()).into());
66+
continue;
67+
}
68+
if let Some(full_refname) = branch.set_head(new, repo)? {
69+
already_updated_refs.push(full_refname);
7770
updated_refs.push(UpdatedReference {
7871
old_commit_id: old,
7972
new_commit_id: new,

crates/but-workspace/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ impl StackEntry {
140140
Ok(StackEntry {
141141
id: stack.id,
142142
heads: stack_heads_info(stack, repo)?,
143-
tip: stack.head(repo)?,
143+
tip: stack.head_oid(repo)?,
144144
})
145145
}
146146
}

crates/but-workspace/tests/fixtures/scenario/three-commits-with-line-offset-and-workspace-commit.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ git init
1010
seq 10 >file
1111
git add . && git commit -m init && git tag first-commit
1212

13-
{ seq 4; seq 10; } >file && git commit -am "insert 5 lines to the top"
13+
{ seq 4; seq 10; } >file && git commit -am "insert 5 lines to the top" && git branch feat1
1414

1515
git commit -m $'GitButler Workspace Commit\n\njust a fake - only the subject matters right now' --allow-empty

crates/but-workspace/tests/workspace/commit_engine/refs_update.rs

Lines changed: 24 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ fn new_commits_to_tip_from_unborn_head() -> anyhow::Result<()> {
110110
// The HEAD reference was updated, along with all other tag-references that pointed to it.
111111
let new_commit = outcome.new_commit.expect("a new commit was created");
112112
insta::assert_snapshot!(visualize_commit_graph(&repo, new_commit)?, @r"
113-
* 1c4bb33 (HEAD -> main, another-tip) third commit
114-
* f1b87da (tag: tag-that-should-not-move) second commit
113+
* 1c4bb33 (HEAD -> main) third commit
114+
* f1b87da (tag: tag-that-should-not-move, another-tip) second commit
115115
* 0939187 initial commit
116116
");
117117

@@ -132,8 +132,8 @@ fn new_commits_to_tip_from_unborn_head() -> anyhow::Result<()> {
132132
assure_no_worktree_changes(&repo)?;
133133
// The top commit has a different hash now thanks to amending.
134134
insta::assert_snapshot!(graph_commit_outcome(&repo, &outcome)?, @r"
135-
* 2abfa5c (HEAD -> main, another-tip) third commit
136-
* f1b87da (tag: tag-that-should-not-move) second commit
135+
* 2abfa5c (HEAD -> main) third commit
136+
* f1b87da (tag: tag-that-should-not-move, another-tip) second commit
137137
* 0939187 initial commit
138138
");
139139

@@ -194,15 +194,6 @@ fn new_commits_to_tip_from_unborn_head() -> anyhow::Result<()> {
194194
Sha1(273aeca7ca98af0f7972af6e7859a3ae7fde497a),
195195
),
196196
references: [
197-
UpdatedReference {
198-
reference: Git(
199-
FullName(
200-
"refs/heads/another-tip",
201-
),
202-
),
203-
old_commit_id: Sha1(2abfa5cc3c7c48b8b9eabbd10c21b88347801f15),
204-
new_commit_id: Sha1(189ac82eb44ddb97677d7d7b1859cf6f2e33a473),
205-
},
206197
UpdatedReference {
207198
reference: Git(
208199
FullName(
@@ -234,9 +225,9 @@ fn new_commits_to_tip_from_unborn_head() -> anyhow::Result<()> {
234225
write_vrbranches_to_refs(&vb, &repo)?;
235226
// It updates stack heads and stack branch heads.
236227
insta::assert_snapshot!(graph_commit_outcome(&repo, &outcome)?, @r"
237-
* 189ac82 (HEAD -> main, s2-b/second, s1-b/second, another-tip) fourth commit
228+
* 189ac82 (HEAD -> main, s2-b/second, s1-b/second) fourth commit
238229
* 2abfa5c third commit
239-
* f1b87da (tag: tag-that-should-not-move, s2-b/first, s1-b/first) second commit
230+
* f1b87da (tag: tag-that-should-not-move, s2-b/first, s1-b/first, another-tip) second commit
240231
* 0939187 (s2-b/init, s1-b/init) initial commit
241232
");
242233
insta::assert_snapshot!(visualize_tree(&repo, &outcome)?, @r#"
@@ -258,7 +249,6 @@ fn new_commits_to_tip_from_unborn_head() -> anyhow::Result<()> {
258249
/// https://github.com/gitbutlerapp/gitbutler/pull/7596 may affect the solution here, but
259250
/// it's not yet ready.
260251
#[test]
261-
#[ignore = "needs fixes"]
262252
fn new_stack_receives_commit_and_adds_it_to_workspace_commit() -> anyhow::Result<()> {
263253
assure_stable_env();
264254

@@ -270,7 +260,7 @@ fn new_stack_receives_commit_and_adds_it_to_workspace_commit() -> anyhow::Result
270260
let workspace_commit_id = repo.rev_parse_single("@")?.detach();
271261
insta::assert_snapshot!(visualize_commit_graph(&repo, workspace_commit_id)?, @r"
272262
* 47c9e16 (HEAD -> main) GitButler Workspace Commit
273-
* b451685 insert 5 lines to the top
263+
* b451685 (feat1) insert 5 lines to the top
274264
* d15b5ae (tag: first-commit) init
275265
");
276266

@@ -311,10 +301,10 @@ fn new_stack_receives_commit_and_adds_it_to_workspace_commit() -> anyhow::Result
311301
// head was updated to point to the new workspace commit.
312302
insta::assert_snapshot!(visualize_commit_graph(&repo, repo.head_id()?)?, @r"
313303
* 7051951 (HEAD -> main) GitButler Workspace Commit
314-
|\
304+
|\
315305
| * 00fbfba (s2/top) new file with 15 lines
316-
* | b451685 (s1/top) insert 5 lines to the top
317-
|/
306+
* | b451685 (s1/top, feat1) insert 5 lines to the top
307+
|/
318308
* d15b5ae (tag: first-commit) init
319309
");
320310

@@ -612,8 +602,8 @@ fn insert_commit_into_single_stack_with_signatures() -> anyhow::Result<()> {
612602
let rewritten_head_id = repo.head_id()?.detach();
613603
insta::assert_snapshot!(visualize_commit_graph(&repo, rewritten_head_id)?, @r"
614604
* 3d1262e (HEAD -> main) insert 10 lines to the top
615-
* 3aec753 (s1-b/init, first-commit) between initial and former first
616-
* ecd6722 (tag: first-commit) init
605+
* 3aec753 (s1-b/init) between initial and former first
606+
* ecd6722 (tag: first-commit, first-commit) init
617607
");
618608
insta::assert_snapshot!(but_testsupport::visualize_tree(rewritten_head_id.attach(&repo)), @r#"
619609
5fdd313
@@ -640,15 +630,6 @@ fn insert_commit_into_single_stack_with_signatures() -> anyhow::Result<()> {
640630
old_commit_id: Sha1(ecd67221705b069c4f46365a46c8f2cd8a97ec19),
641631
new_commit_id: Sha1(3aec75308383b83d85a78a90308a618755a7b0f8),
642632
},
643-
UpdatedReference {
644-
reference: Git(
645-
FullName(
646-
"refs/heads/first-commit",
647-
),
648-
),
649-
old_commit_id: Sha1(ecd67221705b069c4f46365a46c8f2cd8a97ec19),
650-
new_commit_id: Sha1(3aec75308383b83d85a78a90308a618755a7b0f8),
651-
},
652633
UpdatedReference {
653634
reference: Git(
654635
FullName(
@@ -711,8 +692,8 @@ fn insert_commit_into_single_stack_with_signatures() -> anyhow::Result<()> {
711692
let rewritten_head_id = repo.head_id()?;
712693
insta::assert_snapshot!(visualize_commit_graph(&repo, rewritten_head_id)?, @r"
713694
* 4b649eb (HEAD -> main) insert 10 lines to the top
714-
* d26d789 (s1-b/init, first-commit) between initial and former first
715-
* ecd6722 (tag: first-commit) init
695+
* d26d789 (s1-b/init) between initial and former first
696+
* ecd6722 (tag: first-commit, first-commit) init
716697
");
717698
insta::assert_snapshot!(but_testsupport::visualize_tree(rewritten_head_id), @r#"
718699
683b451
@@ -880,8 +861,8 @@ fn insert_commits_into_workspace() -> anyhow::Result<()> {
880861
* a97960f (HEAD -> merge) Merge branch 'A' into merge
881862
|\
882863
| * 3538622 (A) add 10 to the beginning
883-
* | 46991ae (s1-b/init, B) add 10 more lines at end
884-
* | e81b470 add 10 to the end
864+
* | 46991ae (s1-b/init) add 10 more lines at end
865+
* | e81b470 (B) add 10 to the end
885866
|/
886867
* 9cf2979 (main) init
887868
");
@@ -1007,8 +988,8 @@ fn merge_commit_remains_unsigned_in_remerge() -> anyhow::Result<()> {
1007988
insta::assert_snapshot!(visualize_commit_graph(&repo, rewritten_head_id)?, @r"
1008989
* 595a255 (HEAD -> merge) Merge branch 'A' into merge
1009990
|\
1010-
| * 057f154 (s1-b/top, A) remove 5 lines from beginning
1011-
| * eede47d add 10 to the beginning
991+
| * 057f154 (s1-b/top) remove 5 lines from beginning
992+
| * eede47d (A) add 10 to the beginning
1012993
* | 16fe86e (B) add 10 to the end
1013994
|/
1014995
* 6074509 (main) init
@@ -1228,8 +1209,8 @@ fn commit_on_top_of_branch_in_workspace() -> anyhow::Result<()> {
12281209
insta::assert_snapshot!(visualize_commit_graph(&repo, rewritten_head_id)?, @r"
12291210
* 09ac476 (HEAD -> merge) Merge branch 'A' into merge
12301211
|\
1231-
| * 99f3a1c (s1-b/top, A) remove 5 lines from beginning
1232-
| * 7f389ed (s1-b/below-top) add 10 to the beginning
1212+
| * 99f3a1c (s1-b/top) remove 5 lines from beginning
1213+
| * 7f389ed (s1-b/below-top, A) add 10 to the beginning
12331214
* | 91ef6f6 (s2-b/top, s2-b/below-top, B) add 10 to the end
12341215
|/
12351216
* ff045ef (main) init
@@ -1316,10 +1297,10 @@ fn commit_on_top_of_branch_in_workspace() -> anyhow::Result<()> {
13161297
insta::assert_snapshot!(visualize_commit_graph(&repo, rewritten_head_id)?, @r"
13171298
* 098effd (HEAD -> merge) Merge branch 'A' into merge
13181299
|\
1319-
| * 99f3a1c (s1-b/top, A) remove 5 lines from beginning
1320-
| * 7f389ed (s1-b/below-top) add 10 to the beginning
1321-
* | 03e9b6f (s2-b/top, B) remove 5 lines from the end
1322-
* | 91ef6f6 (s2-b/below-top) add 10 to the end
1300+
| * 99f3a1c (s1-b/top) remove 5 lines from beginning
1301+
| * 7f389ed (s1-b/below-top, A) add 10 to the beginning
1302+
* | 03e9b6f (s2-b/top) remove 5 lines from the end
1303+
* | 91ef6f6 (s2-b/below-top, B) add 10 to the end
13231304
|/
13241305
* ff045ef (main) init
13251306
");

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ pub fn create_virtual_branch(
111111
Ok(StackEntry {
112112
id: stack.id,
113113
heads: stack_heads_info(&stack, &repo)?,
114-
tip: stack.head(&repo)?,
114+
tip: stack.head_oid(&repo)?,
115115
})
116116
}
117117

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fn go_back_to_integration(ctx: &CommandContext, default_target: &Target) -> Resu
8282
for branch in &virtual_branches {
8383
// merge this branches tree with our tree
8484
let branch_tree_id = git2_to_gix_object_id(
85-
repo.find_commit(branch.head(&gix_repo)?.to_git2())
85+
repo.find_commit(branch.head_oid(&gix_repo)?.to_git2())
8686
.context("failed to find branch head")?
8787
.tree_id(),
8888
);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ fn branch_group_to_branch(
298298
// If there is a virtual branch let's get it's head. Alternatively, pick the first local branch and use it's head.
299299
// If there are no local branches, pick the first remote branch.
300300
let head_commit = if let Some(vbranch) = virtual_branch {
301-
Some(vbranch.head(repo)?.attach(repo))
301+
Some(vbranch.head_oid(repo)?.attach(repo))
302302
} else if let Some(mut branch) = local_branches.into_iter().next() {
303303
branch.peel_to_id_in_place_packed(packed).ok()
304304
} else if let Some(mut branch) = remote_branches.into_iter().next() {

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,11 +289,11 @@ impl BranchManager<'_> {
289289

290290
let gix_repo = repo.to_gix()?;
291291
let merge_base = repo
292-
.merge_base(default_target.sha, stack.head(&gix_repo)?.to_git2())
292+
.merge_base(default_target.sha, stack.head_oid(&gix_repo)?.to_git2())
293293
.context(format!(
294294
"failed to find merge base between {} and {}",
295295
default_target.sha,
296-
stack.head(&gix_repo)?
296+
stack.head_oid(&gix_repo)?
297297
))?;
298298

299299
// Branch is out of date, merge or rebase it
@@ -331,7 +331,7 @@ impl BranchManager<'_> {
331331
// Do we need to rebase the branch on top of the default target?
332332

333333
let has_change_id = repo
334-
.find_commit(stack.head(&gix_repo)?.to_git2())?
334+
.find_commit(stack.head_oid(&gix_repo)?.to_git2())?
335335
.change_id()
336336
.is_some();
337337
// If the branch has no change ID for the head commit, we want to rebase it even if the base is the same
@@ -351,7 +351,7 @@ impl BranchManager<'_> {
351351
} else {
352352
gitbutler_merge_commits(
353353
repo,
354-
repo.find_commit(stack.head(&gix_repo)?.to_git2())?,
354+
repo.find_commit(stack.head_oid(&gix_repo)?.to_git2())?,
355355
repo.find_commit(default_target.sha)?,
356356
&stack.name,
357357
default_target.branch.branch(),
@@ -378,7 +378,8 @@ impl BranchManager<'_> {
378378

379379
{
380380
if let Some(wip_commit_to_unapply) = &stack.not_in_workspace_wip_change_id {
381-
let potential_wip_commit = repo.find_commit(stack.head(&gix_repo)?.to_git2())?;
381+
let potential_wip_commit =
382+
repo.find_commit(stack.head_oid(&gix_repo)?.to_git2())?;
382383

383384
// Don't try to undo commit if its conflicted
384385
if !potential_wip_commit.is_conflicted() {
@@ -387,7 +388,7 @@ impl BranchManager<'_> {
387388
stack = crate::undo_commit::undo_commit(
388389
self.ctx,
389390
stack.id,
390-
stack.head(&gix_repo)?.to_git2(),
391+
stack.head_oid(&gix_repo)?.to_git2(),
391392
perm,
392393
)?;
393394
}

0 commit comments

Comments
 (0)