Skip to content

Commit 7113a2a

Browse files
committed
Add dropped references to graph overlay
This lets us emulate a reference that has been deleted as part of a graph overlay. uit tool changes
1 parent 0773d20 commit 7113a2a

4 files changed

Lines changed: 197 additions & 1 deletion

File tree

crates/but-graph/src/init/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ pub struct Overlay {
3434
entrypoint: Entrypoint,
3535
nonoverriding_references: Vec<gix::refs::Reference>,
3636
overriding_references: Vec<gix::refs::Reference>,
37+
/// A list of references that should not be picked up anymore in the
38+
/// re-traversal.
39+
///
40+
/// For example, if the `but_rebase::graph_rebase::Editor` converts a
41+
/// `Reference` step to a `None` step which is the equivalent of running
42+
/// `git update-ref -d`, it should no longer be part of the [`Graph`], so we
43+
/// would list the particular reference as a dropped reference.
44+
dropped_references: Vec<gix::refs::FullName>,
3745
meta_branches: Vec<(gix::refs::FullName, ref_metadata::Branch)>,
3846
workspace: Option<(gix::refs::FullName, ref_metadata::Workspace)>,
3947
}

crates/but-graph/src/init/overlay.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ impl Overlay {
3333
self
3434
}
3535

36+
/// A list of references that should not be picked up anymore in the
37+
/// re-traversal.
38+
///
39+
/// For example, if the `but_rebase::graph_rebase::Editor` converts a
40+
/// `Reference` step to a `None` step which is the equivalent of running
41+
/// `git update-ref -d`, it should no longer be part of the [`Graph`], so we
42+
/// would list the particular reference as a dropped reference.
43+
pub fn with_dropped_references(
44+
mut self,
45+
refs: impl IntoIterator<Item = gix::refs::FullName>,
46+
) -> Self {
47+
self.dropped_references.extend(refs);
48+
self
49+
}
50+
3651
/// Override the starting position of the traversal by setting it to `id`,
3752
/// and optionally, by providing the `ref_name` that points to `id`.
3853
pub fn with_entrypoint(
@@ -84,6 +99,7 @@ impl Overlay {
8499
let Overlay {
85100
nonoverriding_references,
86101
overriding_references,
102+
dropped_references,
87103
meta_branches,
88104
workspace,
89105
entrypoint,
@@ -98,6 +114,7 @@ impl Overlay {
98114
.into_iter()
99115
.map(|r| (r.name.clone(), r))
100116
.collect(),
117+
dropped_references: dropped_references.into_iter().collect(),
101118
inner: repo,
102119
},
103120
OverlayMetadata {
@@ -116,6 +133,7 @@ pub(crate) struct OverlayRepo<'repo> {
116133
inner: &'repo gix::Repository,
117134
nonoverriding_references: NameToReference,
118135
overriding_references: NameToReference,
136+
dropped_references: BTreeSet<gix::refs::FullName>,
119137
}
120138

121139
/// Note that functions with `'repo` in their return value technically leak the bare repo, and it's
@@ -129,7 +147,9 @@ impl<'repo> OverlayRepo<'repo> {
129147
&self,
130148
ref_name: &gix::refs::FullNameRef,
131149
) -> anyhow::Result<Option<gix::Reference<'repo>>> {
132-
if let Some(r) = self.overriding_references.get(ref_name) {
150+
if self.dropped_references.contains(ref_name) {
151+
Ok(None)
152+
} else if let Some(r) = self.overriding_references.get(ref_name) {
133153
Ok(Some(r.clone().attach(self.inner)))
134154
} else if let Some(rn) = self.inner.try_find_reference(ref_name)? {
135155
Ok(Some(rn))
@@ -144,6 +164,11 @@ impl<'repo> OverlayRepo<'repo> {
144164
&self,
145165
ref_name: &gix::refs::FullNameRef,
146166
) -> anyhow::Result<gix::Reference<'repo>> {
167+
if self.dropped_references.contains(ref_name) {
168+
bail!(
169+
"Failed to find reference {ref_name} due to it being dropped in the traversal overlay"
170+
);
171+
}
147172
if let Some(r) = self.overriding_references.get(ref_name) {
148173
return Ok(r.clone().attach(self.inner));
149174
}

crates/but-graph/tests/graph/init/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,7 @@ fn commit_with_two_parents() -> anyhow::Result<()> {
932932
Ok(())
933933
}
934934

935+
mod overlay;
935936
mod with_workspace;
936937

937938
pub(crate) mod utils;
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
//! Some tests that expliclity test the overlay functionality
2+
3+
use but_graph::{Graph, init::Overlay};
4+
use but_testsupport::{graph_tree, visualize_commit_graph_all};
5+
6+
use crate::init::{read_only_in_memory_scenario, standard_options};
7+
8+
#[test]
9+
fn drop_and_add_regular_refs() -> anyhow::Result<()> {
10+
let (repo, meta) = read_only_in_memory_scenario("four-diamond")?;
11+
insta::assert_snapshot!(visualize_commit_graph_all(&repo)?, @r"
12+
* 8a6c109 (HEAD -> merged) Merge branch 'C' into merged
13+
|\
14+
| * 7ed512a (C) Merge branch 'D' into C
15+
| |\
16+
| | * ecb1877 (D) D
17+
| * | 35ee481 C
18+
| |/
19+
* | 62b409a (A) Merge branch 'B' into A
20+
|\ \
21+
| * | f16dddf (B) B
22+
| |/
23+
* / 592abec A
24+
|/
25+
* 965998b (main) base
26+
");
27+
28+
let graph = Graph::from_head(&repo, &*meta, standard_options())?;
29+
insta::assert_snapshot!(graph_tree(&graph), @r"
30+
31+
└── 👉►:0[0]:merged[🌳]
32+
└── ·8a6c109 (⌂|1)
33+
├── ►:1[1]:A
34+
│ └── ·62b409a (⌂|1)
35+
│ ├── ►:3[2]:anon:
36+
│ │ └── ·592abec (⌂|1)
37+
│ │ └── ►:7[3]:main
38+
│ │ └── ·965998b (⌂|1)
39+
│ └── ►:4[2]:B
40+
│ └── ·f16dddf (⌂|1)
41+
│ └── →:7: (main)
42+
└── ►:2[1]:C
43+
└── ·7ed512a (⌂|1)
44+
├── ►:5[2]:anon:
45+
│ └── ·35ee481 (⌂|1)
46+
│ └── →:7: (main)
47+
└── ►:6[2]:D
48+
└── ·ecb1877 (⌂|1)
49+
└── →:7: (main)
50+
");
51+
52+
let to_reference = repo.rev_parse_single("35ee481")?;
53+
54+
let overlay = Overlay::default()
55+
.with_references([gix::refs::Reference {
56+
name: "refs/heads/new-reference".try_into()?,
57+
target: gix::refs::Target::Object(to_reference.detach()),
58+
peeled: Some(to_reference.detach()),
59+
}])
60+
.with_dropped_references(["refs/heads/C".try_into()?]);
61+
62+
let graph = graph.redo_traversal_with_overlay(&repo, &*meta, overlay)?;
63+
64+
insta::assert_snapshot!(graph_tree(&graph), @"
65+
66+
└── 👉►:0[0]:merged[🌳]
67+
└── ·8a6c109 (⌂|1)
68+
├── ►:1[1]:A
69+
│ └── ·62b409a (⌂|1)
70+
│ ├── ►:3[2]:anon:
71+
│ │ └── ·592abec (⌂|1)
72+
│ │ └── ►:7[3]:main
73+
│ │ └── ·965998b (⌂|1)
74+
│ └── ►:4[2]:B
75+
│ └── ·f16dddf (⌂|1)
76+
│ └── →:7: (main)
77+
└── ►:2[1]:anon:
78+
└── ·7ed512a (⌂|1)
79+
├── ►:5[2]:new-reference
80+
│ └── ·35ee481 (⌂|1)
81+
│ └── →:7: (main)
82+
└── ►:6[2]:D
83+
└── ·ecb1877 (⌂|1)
84+
└── →:7: (main)
85+
");
86+
87+
Ok(())
88+
}
89+
90+
#[test]
91+
fn drop_head_ref() -> anyhow::Result<()> {
92+
let (repo, meta) = read_only_in_memory_scenario("four-diamond")?;
93+
insta::assert_snapshot!(visualize_commit_graph_all(&repo)?, @r"
94+
* 8a6c109 (HEAD -> merged) Merge branch 'C' into merged
95+
|\
96+
| * 7ed512a (C) Merge branch 'D' into C
97+
| |\
98+
| | * ecb1877 (D) D
99+
| * | 35ee481 C
100+
| |/
101+
* | 62b409a (A) Merge branch 'B' into A
102+
|\ \
103+
| * | f16dddf (B) B
104+
| |/
105+
* / 592abec A
106+
|/
107+
* 965998b (main) base
108+
");
109+
110+
let graph = Graph::from_head(&repo, &*meta, standard_options())?;
111+
insta::assert_snapshot!(graph_tree(&graph), @r"
112+
113+
└── 👉►:0[0]:merged[🌳]
114+
└── ·8a6c109 (⌂|1)
115+
├── ►:1[1]:A
116+
│ └── ·62b409a (⌂|1)
117+
│ ├── ►:3[2]:anon:
118+
│ │ └── ·592abec (⌂|1)
119+
│ │ └── ►:7[3]:main
120+
│ │ └── ·965998b (⌂|1)
121+
│ └── ►:4[2]:B
122+
│ └── ·f16dddf (⌂|1)
123+
│ └── →:7: (main)
124+
└── ►:2[1]:C
125+
└── ·7ed512a (⌂|1)
126+
├── ►:5[2]:anon:
127+
│ └── ·35ee481 (⌂|1)
128+
│ └── →:7: (main)
129+
└── ►:6[2]:D
130+
└── ·ecb1877 (⌂|1)
131+
└── →:7: (main)
132+
");
133+
134+
let overlay = Overlay::default().with_dropped_references(["refs/heads/merged".try_into()?]);
135+
136+
let graph = graph.redo_traversal_with_overlay(&repo, &*meta, overlay)?;
137+
138+
insta::assert_snapshot!(graph_tree(&graph), @"
139+
140+
└── ►:0[0]:anon:
141+
└── 👉·8a6c109 (⌂|1)
142+
├── ►:1[1]:A
143+
│ └── ·62b409a (⌂|1)
144+
│ ├── ►:3[2]:anon:
145+
│ │ └── ·592abec (⌂|1)
146+
│ │ └── ►:7[3]:main
147+
│ │ └── ·965998b (⌂|1)
148+
│ └── ►:4[2]:B
149+
│ └── ·f16dddf (⌂|1)
150+
│ └── →:7: (main)
151+
└── ►:2[1]:C
152+
└── ·7ed512a (⌂|1)
153+
├── ►:5[2]:anon:
154+
│ └── ·35ee481 (⌂|1)
155+
│ └── →:7: (main)
156+
└── ►:6[2]:D
157+
└── ·ecb1877 (⌂|1)
158+
└── →:7: (main)
159+
");
160+
161+
Ok(())
162+
}

0 commit comments

Comments
 (0)