Skip to content

Commit 41ddded

Browse files
committed
add a test to assure non-workspace refs are *not* updated
1 parent 0072404 commit 41ddded

File tree

6 files changed

+88
-76
lines changed

6 files changed

+88
-76
lines changed

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

Lines changed: 45 additions & 10 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()

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

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,7 @@ pub fn rewrite(
3636
}
3737
}
3838
if stack.head_oid(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();
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/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: 22 additions & 40 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#"
@@ -269,7 +260,7 @@ fn new_stack_receives_commit_and_adds_it_to_workspace_commit() -> anyhow::Result
269260
let workspace_commit_id = repo.rev_parse_single("@")?.detach();
270261
insta::assert_snapshot!(visualize_commit_graph(&repo, workspace_commit_id)?, @r"
271262
* 47c9e16 (HEAD -> main) GitButler Workspace Commit
272-
* b451685 insert 5 lines to the top
263+
* b451685 (feat1) insert 5 lines to the top
273264
* d15b5ae (tag: first-commit) init
274265
");
275266

@@ -312,7 +303,7 @@ fn new_stack_receives_commit_and_adds_it_to_workspace_commit() -> anyhow::Result
312303
* 7051951 (HEAD -> main) GitButler Workspace Commit
313304
|\
314305
| * 00fbfba (s2/top) new file with 15 lines
315-
* | b451685 (s1/top) insert 5 lines to the top
306+
* | b451685 (s1/top, feat1) insert 5 lines to the top
316307
|/
317308
* d15b5ae (tag: first-commit) init
318309
");
@@ -611,8 +602,8 @@ fn insert_commit_into_single_stack_with_signatures() -> anyhow::Result<()> {
611602
let rewritten_head_id = repo.head_id()?.detach();
612603
insta::assert_snapshot!(visualize_commit_graph(&repo, rewritten_head_id)?, @r"
613604
* 3d1262e (HEAD -> main) insert 10 lines to the top
614-
* 3aec753 (s1-b/init, first-commit) between initial and former first
615-
* ecd6722 (tag: first-commit) init
605+
* 3aec753 (s1-b/init) between initial and former first
606+
* ecd6722 (tag: first-commit, first-commit) init
616607
");
617608
insta::assert_snapshot!(but_testsupport::visualize_tree(rewritten_head_id.attach(&repo)), @r#"
618609
5fdd313
@@ -639,15 +630,6 @@ fn insert_commit_into_single_stack_with_signatures() -> anyhow::Result<()> {
639630
old_commit_id: Sha1(ecd67221705b069c4f46365a46c8f2cd8a97ec19),
640631
new_commit_id: Sha1(3aec75308383b83d85a78a90308a618755a7b0f8),
641632
},
642-
UpdatedReference {
643-
reference: Git(
644-
FullName(
645-
"refs/heads/first-commit",
646-
),
647-
),
648-
old_commit_id: Sha1(ecd67221705b069c4f46365a46c8f2cd8a97ec19),
649-
new_commit_id: Sha1(3aec75308383b83d85a78a90308a618755a7b0f8),
650-
},
651633
UpdatedReference {
652634
reference: Git(
653635
FullName(
@@ -710,8 +692,8 @@ fn insert_commit_into_single_stack_with_signatures() -> anyhow::Result<()> {
710692
let rewritten_head_id = repo.head_id()?;
711693
insta::assert_snapshot!(visualize_commit_graph(&repo, rewritten_head_id)?, @r"
712694
* 4b649eb (HEAD -> main) insert 10 lines to the top
713-
* d26d789 (s1-b/init, first-commit) between initial and former first
714-
* ecd6722 (tag: first-commit) init
695+
* d26d789 (s1-b/init) between initial and former first
696+
* ecd6722 (tag: first-commit, first-commit) init
715697
");
716698
insta::assert_snapshot!(but_testsupport::visualize_tree(rewritten_head_id), @r#"
717699
683b451
@@ -879,8 +861,8 @@ fn insert_commits_into_workspace() -> anyhow::Result<()> {
879861
* a97960f (HEAD -> merge) Merge branch 'A' into merge
880862
|\
881863
| * 3538622 (A) add 10 to the beginning
882-
* | 46991ae (s1-b/init, B) add 10 more lines at end
883-
* | 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
884866
|/
885867
* 9cf2979 (main) init
886868
");
@@ -1006,8 +988,8 @@ fn merge_commit_remains_unsigned_in_remerge() -> anyhow::Result<()> {
1006988
insta::assert_snapshot!(visualize_commit_graph(&repo, rewritten_head_id)?, @r"
1007989
* 595a255 (HEAD -> merge) Merge branch 'A' into merge
1008990
|\
1009-
| * 057f154 (s1-b/top, A) remove 5 lines from beginning
1010-
| * eede47d add 10 to the beginning
991+
| * 057f154 (s1-b/top) remove 5 lines from beginning
992+
| * eede47d (A) add 10 to the beginning
1011993
* | 16fe86e (B) add 10 to the end
1012994
|/
1013995
* 6074509 (main) init
@@ -1227,8 +1209,8 @@ fn commit_on_top_of_branch_in_workspace() -> anyhow::Result<()> {
12271209
insta::assert_snapshot!(visualize_commit_graph(&repo, rewritten_head_id)?, @r"
12281210
* 09ac476 (HEAD -> merge) Merge branch 'A' into merge
12291211
|\
1230-
| * 99f3a1c (s1-b/top, A) remove 5 lines from beginning
1231-
| * 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
12321214
* | 91ef6f6 (s2-b/top, s2-b/below-top, B) add 10 to the end
12331215
|/
12341216
* ff045ef (main) init
@@ -1315,10 +1297,10 @@ fn commit_on_top_of_branch_in_workspace() -> anyhow::Result<()> {
13151297
insta::assert_snapshot!(visualize_commit_graph(&repo, rewritten_head_id)?, @r"
13161298
* 098effd (HEAD -> merge) Merge branch 'A' into merge
13171299
|\
1318-
| * 99f3a1c (s1-b/top, A) remove 5 lines from beginning
1319-
| * 7f389ed (s1-b/below-top) add 10 to the beginning
1320-
* | 03e9b6f (s2-b/top, B) remove 5 lines from the end
1321-
* | 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
13221304
|/
13231305
* ff045ef (main) init
13241306
");

crates/gitbutler-stack/src/stack.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,10 @@ impl Stack {
210210
self.try_into()
211211
}
212212

213-
// TODO: derive this from the last head
214213
pub fn head_oid(&self, repo: &gix::Repository) -> Result<gix::ObjectId> {
215214
self.heads
216215
.last()
217-
.map(|head| head.head_oid(repo))
216+
.map(|branch| branch.head_oid(repo))
218217
.ok_or_else(|| anyhow!("Stack is uninitialized"))?
219218
}
220219

crates/gitbutler-stack/src/stack_branch.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,17 @@ impl StackBranch {
143143
}
144144
}
145145

146-
/// This will update the commit that this points to (the virtual reference in virtual_branches.toml) as well as update of create a real git reference.
147-
/// If this points to a change id, it's a noop operation. In practice, moving forward, new CommitOrChangeId entries will always be CommitId and ChangeId may only appear in deserialized data.
148-
pub fn set_head<T>(&mut self, head: T, repo: &gix::Repository) -> Result<Option<BString>>
146+
/// This will update the commit that real git reference points to, so it points to `target`,
147+
/// as well as the cached data in this instance.
148+
/// Returns the full reference name like `refs/heads/name`.
149+
/// If this points to a change id, it's a noop operation. In practice, moving forward, new
150+
/// `CommitOrChangeId` entries will always be CommitId and ChangeId may only appear in deserialized data.
151+
pub fn set_head<T>(&mut self, target: T, repo: &gix::Repository) -> Result<Option<BString>>
149152
where
150153
T: Into<CommitOrChangeId> + Clone,
151154
{
152-
let refname = self.set_real_reference(repo, &head)?;
153-
self.head = head.into();
155+
let refname = self.set_real_reference(repo, &target)?;
156+
self.head = target.into();
154157
Ok(refname)
155158
}
156159

0 commit comments

Comments
 (0)