Skip to content

Commit cbfb19d

Browse files
committed
Add tests for rebase-based scenarios to learn about expensive integration checks and branch info.
1 parent 87196a8 commit cbfb19d

File tree

9 files changed

+292
-60
lines changed

9 files changed

+292
-60
lines changed

crates/but-workspace/src/changeset.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,17 @@ impl RefInfo {
101101
// top-to-bottom
102102
.commits
103103
.iter_mut()
104-
.take_while(|c| c.relation == LocalCommitRelation::LocalOnly)
104+
.take_while(|c| {
105+
matches!(
106+
c.relation,
107+
// This happens when the identity match with the remote didn't work.
108+
LocalCommitRelation::LocalOnly |
109+
// This would be expected to be a remote-match by identity (we don't check for this),
110+
// something that is determined during graph traversal time. But we want ot see
111+
// if any of these is also integrated.
112+
LocalCommitRelation::LocalAndRemote(_)
113+
)
114+
})
105115
{
106116
let expensive = changeset_identifier(repo, expensive.then_some(local))?;
107117
if let Some(upstream_commit_id) =

crates/but-workspace/src/ref_info.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,14 @@ pub mod ui {
160160
/// Convert this relation into something displaying, mainly for debugging.
161161
pub fn display(&self, id: gix::ObjectId) -> Cow<'static, str> {
162162
match self {
163-
LocalCommitRelation::LocalOnly => "local".into(),
164-
LocalCommitRelation::LocalAndRemote(remote_id) => if *remote_id == id {
165-
"local/remote(identity)"
166-
} else {
167-
"local/remote(similarity)"
163+
LocalCommitRelation::LocalOnly => Cow::Borrowed("local"),
164+
LocalCommitRelation::LocalAndRemote(remote_id) => {
165+
if *remote_id == id {
166+
"local/remote(identity)".into()
167+
} else {
168+
format!("local/remote({})", remote_id.to_hex_with_len(7)).into()
169+
}
168170
}
169-
.into(),
170171
LocalCommitRelation::Integrated(id) => {
171172
format!("integrated({})", id.to_hex_with_len(7)).into()
172173
}

crates/but-workspace/tests/fixtures/scenario/journey02.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
### General Description
44

5-
# Various stages through a typical user journey. Ideally complete enough to test everything that matters to us.
5+
# Disjoint scenarios related to remote branches that are merged in.
66
set -eu -o pipefail
77

88
source "${BASH_SOURCE[0]%/*}/shared.sh"
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env bash
2+
3+
### General Description
4+
5+
# Disjoint scenarios related to remote branches that have been rebased and merged.
6+
set -eu -o pipefail
7+
8+
source "${BASH_SOURCE[0]%/*}/shared.sh"
9+
10+
git init 01-one-rewritten-one-local-after-push
11+
(cd 01-one-rewritten-one-local-after-push
12+
echo "two local commits pushed to a remote, then rebased onto target.
13+
14+
The branch should then be considered integrated" >.git/description
15+
commit init && setup_target_to_match_main
16+
git checkout -b A
17+
echo A-new >file && git add file && git commit -m A1
18+
echo A-new >other && git add other && git commit -m A2
19+
git rev-parse @ >.git/refs/remotes/origin/A
20+
21+
git checkout main
22+
commit M1
23+
git cherry-pick :/A1
24+
git cherry-pick :/A2
25+
echo M-change >>file && git commit -am M2
26+
echo M-change >>other && git commit -am M3
27+
git rev-parse @ >.git/refs/remotes/origin/main
28+
29+
git checkout A
30+
create_workspace_commit_once A
31+
)
32+
33+
git init 01-one-rewritten-one-local-after-push-author-date-change
34+
(cd 01-one-rewritten-one-local-after-push-author-date-change
35+
echo "two local commits pushed to a remote, then rebased onto target, but with the author date adjusted.
36+
37+
This prevents quick-checks to work." >.git/description
38+
commit init && setup_target_to_match_main
39+
git checkout -b A
40+
echo A-new >file && git add file && git commit -m A1
41+
echo A-new >other && git add other && git commit -m A2
42+
git rev-parse @ >.git/refs/remotes/origin/A
43+
44+
git checkout main
45+
commit M1
46+
tick
47+
git cherry-pick :/A1
48+
tick
49+
git cherry-pick :/A2
50+
echo M-change >>file && git commit -am M2
51+
echo M-change >>other && git commit -am M3
52+
git rev-parse @ >.git/refs/remotes/origin/main
53+
54+
git checkout A
55+
create_workspace_commit_once A
56+
)

crates/but-workspace/tests/workspace/ref_info/with_workspace_commit/journey/exhaustive_with_squash_merges.rs

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -561,54 +561,54 @@ fn j09_rewritten_remote_and_local_commit() -> anyhow::Result<()> {
561561
add_stack_with_segments(&mut meta, 0, "S1", StackState::InWorkspace, &[]);
562562
let info = but_workspace::head_info(&repo, &*meta, standard_options());
563563
insta::assert_debug_snapshot!(info, @r#"
564-
Ok(
565-
RefInfo {
566-
workspace_ref_name: Some(
567-
FullName(
568-
"refs/heads/gitbutler/workspace",
569-
),
570-
),
571-
stacks: [
572-
Stack {
573-
base: Some(
574-
Sha1(fafd9d08a839d99db60b222cd58e2e0bfaf1f7b2),
564+
Ok(
565+
RefInfo {
566+
workspace_ref_name: Some(
567+
FullName(
568+
"refs/heads/gitbutler/workspace",
575569
),
576-
segments: [
577-
ref_info::ui::Segment {
578-
id: NodeIndex(3),
579-
ref_name: "refs/heads/S1",
580-
remote_tracking_ref_name: "refs/remotes/origin/S1",
581-
commits: [
582-
LocalCommit(314cacb, "two\n", local/remote(similarity)),
583-
LocalCommit(3234835, "one\n", local/remote(identity)),
584-
],
585-
commits_unique_in_remote_tracking_branch: [],
586-
metadata: Branch,
587-
push_status: UnpushedCommitsRequiringForce,
588-
base: "fafd9d0",
589-
},
590-
],
591-
},
592-
],
593-
target: Some(
594-
Target {
595-
ref_name: FullName(
596-
"refs/remotes/origin/main",
597-
),
598-
segment_index: NodeIndex(1),
599-
commits_ahead: 0,
600-
},
601-
),
602-
extra_target: None,
603-
lower_bound: Some(
604-
NodeIndex(2),
605-
),
606-
is_managed_ref: true,
607-
is_managed_commit: true,
608-
is_entrypoint: true,
609-
},
610-
)
611-
"#);
570+
),
571+
stacks: [
572+
Stack {
573+
base: Some(
574+
Sha1(fafd9d08a839d99db60b222cd58e2e0bfaf1f7b2),
575+
),
576+
segments: [
577+
ref_info::ui::Segment {
578+
id: NodeIndex(3),
579+
ref_name: "refs/heads/S1",
580+
remote_tracking_ref_name: "refs/remotes/origin/S1",
581+
commits: [
582+
LocalCommit(314cacb, "two\n", local/remote(9a2fcdf)),
583+
LocalCommit(3234835, "one\n", local/remote(identity)),
584+
],
585+
commits_unique_in_remote_tracking_branch: [],
586+
metadata: Branch,
587+
push_status: UnpushedCommitsRequiringForce,
588+
base: "fafd9d0",
589+
},
590+
],
591+
},
592+
],
593+
target: Some(
594+
Target {
595+
ref_name: FullName(
596+
"refs/remotes/origin/main",
597+
),
598+
segment_index: NodeIndex(1),
599+
commits_ahead: 0,
600+
},
601+
),
602+
extra_target: None,
603+
lower_bound: Some(
604+
NodeIndex(2),
605+
),
606+
is_managed_ref: true,
607+
is_managed_commit: true,
608+
is_entrypoint: true,
609+
},
610+
)
611+
"#);
612612
Ok(())
613613
}
614614

crates/but-workspace/tests/workspace/ref_info/with_workspace_commit/journey/integrate_with_merges.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ fn two_commits_require_force_push() -> anyhow::Result<()> {
4343
remote_tracking_ref_name: "refs/remotes/origin/A",
4444
commits: [
4545
LocalCommit(f9c2b14, "A2\n", local),
46-
LocalCommit(e1f216e, "A1\n", local/remote(similarity)),
46+
LocalCommit(e1f216e, "A1\n", local/remote(3fcd07a)),
4747
],
4848
commits_unique_in_remote_tracking_branch: [],
4949
metadata: "None",
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
//! A loose collection of states that users typically encounter.
2+
use crate::ref_info::utils::standard_options;
3+
use crate::ref_info::with_workspace_commit::utils::named_read_only_in_memory_scenario_with_description;
4+
use but_graph::VirtualBranchesTomlMetadata;
5+
use but_testsupport::visualize_commit_graph_all;
6+
7+
#[test]
8+
fn two_commits_rebased_onto_target() -> anyhow::Result<()> {
9+
let (repo, meta, description) = scenario("01-one-rewritten-one-local-after-push")?;
10+
insta::assert_snapshot!(description, @r"
11+
two local commits pushed to a remote, then rebased onto target.
12+
13+
The branch should then be considered integrated
14+
");
15+
insta::assert_snapshot!(visualize_commit_graph_all(&repo)?, @r"
16+
* 946cdb7 (HEAD -> gitbutler/workspace) GitButler Workspace Commit
17+
* f9c2b14 (origin/A, A) A2
18+
* e1f216e A1
19+
| * eabf298 (origin/main, main) M3
20+
| * 1ff86ae M2
21+
| * 36c87e5 A2
22+
| * 818dbb2 A1
23+
| * ce09734 M1
24+
|/
25+
* fafd9d0 init
26+
");
27+
28+
let info = but_workspace::head_info(&repo, &*meta, standard_options());
29+
insta::assert_debug_snapshot!(info, @r#"
30+
Ok(
31+
RefInfo {
32+
workspace_ref_name: Some(
33+
FullName(
34+
"refs/heads/gitbutler/workspace",
35+
),
36+
),
37+
stacks: [
38+
Stack {
39+
base: Some(
40+
Sha1(fafd9d08a839d99db60b222cd58e2e0bfaf1f7b2),
41+
),
42+
segments: [
43+
ref_info::ui::Segment {
44+
id: NodeIndex(3),
45+
ref_name: "refs/heads/A",
46+
remote_tracking_ref_name: "refs/remotes/origin/A",
47+
commits: [
48+
LocalCommit(f9c2b14, "A2\n", integrated(36c87e5)),
49+
LocalCommit(e1f216e, "A1\n", integrated(818dbb2)),
50+
],
51+
commits_unique_in_remote_tracking_branch: [],
52+
metadata: "None",
53+
push_status: Integrated,
54+
base: "fafd9d0",
55+
},
56+
],
57+
},
58+
],
59+
target: Some(
60+
Target {
61+
ref_name: FullName(
62+
"refs/remotes/origin/main",
63+
),
64+
segment_index: NodeIndex(1),
65+
commits_ahead: 0,
66+
},
67+
),
68+
extra_target: None,
69+
lower_bound: Some(
70+
NodeIndex(5),
71+
),
72+
is_managed_ref: true,
73+
is_managed_commit: true,
74+
is_entrypoint: true,
75+
},
76+
)
77+
"#);
78+
Ok(())
79+
}
80+
81+
#[test]
82+
fn two_commits_rebased_onto_target_with_changeset_check() -> anyhow::Result<()> {
83+
let (repo, meta, description) =
84+
scenario("01-one-rewritten-one-local-after-push-author-date-change")?;
85+
insta::assert_snapshot!(description, @r"
86+
two local commits pushed to a remote, then rebased onto target, but with the author date adjusted.
87+
88+
This prevents quick-checks to work.
89+
");
90+
insta::assert_snapshot!(visualize_commit_graph_all(&repo)?, @r"
91+
* f1caa51 (HEAD -> gitbutler/workspace) GitButler Workspace Commit
92+
* f9c2b14 (origin/A, A) A2
93+
* e1f216e A1
94+
| * 7a2d071 (origin/main, main) M3
95+
| * 34dac9d M2
96+
| * 85063c1 A2
97+
| * 444639d A1
98+
| * ce09734 M1
99+
|/
100+
* fafd9d0 init
101+
");
102+
103+
let info = but_workspace::head_info(&repo, &*meta, standard_options());
104+
insta::assert_debug_snapshot!(info, @r#"
105+
Ok(
106+
RefInfo {
107+
workspace_ref_name: Some(
108+
FullName(
109+
"refs/heads/gitbutler/workspace",
110+
),
111+
),
112+
stacks: [
113+
Stack {
114+
base: Some(
115+
Sha1(fafd9d08a839d99db60b222cd58e2e0bfaf1f7b2),
116+
),
117+
segments: [
118+
ref_info::ui::Segment {
119+
id: NodeIndex(3),
120+
ref_name: "refs/heads/A",
121+
remote_tracking_ref_name: "refs/remotes/origin/A",
122+
commits: [
123+
LocalCommit(f9c2b14, "A2\n", integrated(85063c1)),
124+
LocalCommit(e1f216e, "A1\n", integrated(444639d)),
125+
],
126+
commits_unique_in_remote_tracking_branch: [],
127+
metadata: "None",
128+
push_status: Integrated,
129+
base: "fafd9d0",
130+
},
131+
],
132+
},
133+
],
134+
target: Some(
135+
Target {
136+
ref_name: FullName(
137+
"refs/remotes/origin/main",
138+
),
139+
segment_index: NodeIndex(1),
140+
commits_ahead: 0,
141+
},
142+
),
143+
extra_target: None,
144+
lower_bound: Some(
145+
NodeIndex(5),
146+
),
147+
is_managed_ref: true,
148+
is_managed_commit: true,
149+
is_entrypoint: true,
150+
},
151+
)
152+
"#);
153+
Ok(())
154+
}
155+
156+
pub fn scenario(
157+
name: &str,
158+
) -> anyhow::Result<(
159+
gix::Repository,
160+
std::mem::ManuallyDrop<VirtualBranchesTomlMetadata>,
161+
String,
162+
)> {
163+
named_read_only_in_memory_scenario_with_description("journey03", name)
164+
}

crates/but-workspace/tests/workspace/ref_info/with_workspace_commit/journey/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod exhaustive_with_squash_merges;
22
mod integrate_with_merges;
3+
mod integrate_with_rebase;
34

45
mod utils {
56
use crate::ref_info::utils::standard_options;

0 commit comments

Comments
 (0)