Skip to content

Commit 266bede

Browse files
committed
feat: add Graph::insert_parents_with_lookup() and Graph::insert_data().
It's another way to insert parents, and tuned for the needs of merge-base. `insert_data()` makes it easy to insert data for a single commit.
1 parent 3bc7628 commit 266bede

File tree

1 file changed

+55
-1
lines changed

1 file changed

+55
-1
lines changed

gix-revwalk/src/graph/mod.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,26 @@ impl<'find, T> Graph<'find, T> {
9090
self.map.get_mut(id)
9191
}
9292

93-
/// Insert `id` into the graph and associate it with `value`, returning the previous value associated with it if it existed.
93+
/// Insert `id` into the graph and associate it with `value`, returning the previous value associated with `id` if it existed.
9494
pub fn insert(&mut self, id: gix_hash::ObjectId, value: T) -> Option<T> {
9595
self.map.insert(id, value)
9696
}
9797

98+
/// Insert `id` into the graph and associate it with the value returned by `make_data`,
99+
/// and returning the previous value associated with `id` if it existed.
100+
/// Fail if `id` doesn't exist in the object database.
101+
pub fn insert_data<E>(
102+
&mut self,
103+
id: gix_hash::ObjectId,
104+
mut make_data: impl FnMut(LazyCommit<'_>) -> Result<T, E>,
105+
) -> Result<Option<T>, E>
106+
where
107+
E: From<gix_object::find::existing_iter::Error>,
108+
{
109+
let value = make_data(self.lookup(&id).map_err(E::from)?)?;
110+
Ok(self.map.insert(id, value))
111+
}
112+
98113
/// Remove all data from the graph to start over.
99114
pub fn clear(&mut self) {
100115
self.map.clear();
@@ -136,6 +151,45 @@ impl<'find, T> Graph<'find, T> {
136151
Ok(())
137152
}
138153

154+
/// Insert the parents of commit named `id` to the graph and associate new parents with data
155+
/// as produced by `parent_data(parent_id, parent_info, maybe-existing-data &mut T) -> T`, which is always
156+
/// provided the full parent commit information.
157+
/// It will be provided either existing data, along with complete information about the parent,
158+
/// and produces new data even though it's only used in case the parent isn't stored in the graph yet.
159+
#[allow(clippy::type_complexity)]
160+
pub fn insert_parents_with_lookup<E>(
161+
&mut self,
162+
id: &gix_hash::oid,
163+
parent_data: &mut dyn FnMut(gix_hash::ObjectId, LazyCommit<'_>, Option<&mut T>) -> Result<T, E>,
164+
) -> Result<(), E>
165+
where
166+
E: From<gix_object::find::existing_iter::Error>
167+
+ From<gix_object::decode::Error>
168+
+ From<commit::iter_parents::Error>,
169+
{
170+
let commit = self.lookup(id).map_err(E::from)?;
171+
let parents: SmallVec<[_; 2]> = commit.iter_parents().collect();
172+
for parent_id in parents {
173+
let parent_id = parent_id.map_err(E::from)?;
174+
let parent = match try_lookup(&parent_id, &*self.find, self.cache.as_ref(), &mut self.parent_buf)
175+
.map_err(E::from)?
176+
{
177+
Some(p) => p,
178+
None => continue, // skip missing objects, this is due to shallow clones for instance.
179+
};
180+
181+
match self.map.entry(parent_id) {
182+
gix_hashtable::hash_map::Entry::Vacant(entry) => {
183+
entry.insert(parent_data(parent_id, parent, None)?);
184+
}
185+
gix_hashtable::hash_map::Entry::Occupied(mut entry) => {
186+
parent_data(parent_id, parent, Some(entry.get_mut()))?;
187+
}
188+
}
189+
}
190+
Ok(())
191+
}
192+
139193
/// Turn ourselves into the underlying graph structure, which is a mere mapping between object ids and their data.
140194
pub fn detach(self) -> IdMap<T> {
141195
self.map

0 commit comments

Comments
 (0)