Skip to content

Commit 3b453da

Browse files
committed
feat: add Graph::get_or_insert_full_commit()
A way to insert a full commit with a single update functions that has access to the full commit, not just the data.
1 parent 1c44e41 commit 3b453da

File tree

1 file changed

+33
-5
lines changed

1 file changed

+33
-5
lines changed

gix-revwalk/src/graph/mod.rs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,9 @@ impl<'find, 'cache, T> Graph<'find, 'cache, T> {
226226
}
227227

228228
/// Commit based methods
229-
impl<'find, 'cache, T> Graph<'find, 'cache, crate::graph::Commit<T>> {
230-
/// Lookup `id` without failing if the commit doesn't exist, and assure that `id` is inserted into our set
231-
/// with a commit with `new_data()` assigned.
229+
impl<'find, 'cache, T> Graph<'find, 'cache, Commit<T>> {
230+
/// Lookup `id` in the graph, but insert it if it's not yet present by looking it up without failing if the commit doesn't exist.
231+
/// Call `new_data()` to obtain data for a newly inserted commit.
232232
/// `update_data(data)` gets run either on existing or on new data.
233233
///
234234
/// Note that none of the data updates happen if `id` didn't exist.
@@ -264,8 +264,8 @@ impl<'find, 'cache, T> Graph<'find, 'cache, crate::graph::Commit<T>> {
264264

265265
/// Commit based methods
266266
impl<'find, 'cache, T: Default> Graph<'find, 'cache, Commit<T>> {
267-
/// Lookup `id` without failing if the commit doesn't exist or `id` isn't a commit,
268-
/// and assure that `id` is inserted into our set with a commit and default data assigned.
267+
/// Lookup `id` in the graph, but insert it if it's not yet present by looking it up without failing if the commit doesn't exist.
268+
/// Newly inserted commits are populated with default data.
269269
/// `update_data(data)` gets run either on existing or on new data.
270270
///
271271
/// Note that none of the data updates happen if `id` didn't exist.
@@ -279,6 +279,34 @@ impl<'find, 'cache, T: Default> Graph<'find, 'cache, Commit<T>> {
279279
) -> Result<Option<&mut Commit<T>>, try_lookup_or_insert_default::Error> {
280280
self.try_lookup_or_insert_commit_default(id, T::default, update_data)
281281
}
282+
283+
/// Lookup `id` in the graph, but insert it if it's not yet present by looking it up without failing if the commit doesn't exist.
284+
/// `update_commit(commit, is_new)` gets run either on existing or on new data, with `is_new`
285+
/// being true if the `commit` was newly inserted.
286+
///
287+
/// Note that none of the data updates happen if `id` didn't exist in the graph.
288+
pub fn get_or_insert_full_commit(
289+
&mut self,
290+
id: gix_hash::ObjectId,
291+
update_commit: impl FnOnce(&mut Commit<T>, bool),
292+
) -> Result<Option<&mut Commit<T>>, try_lookup_or_insert_default::Error> {
293+
match self.map.entry(id) {
294+
gix_hashtable::hash_map::Entry::Vacant(entry) => {
295+
let res = try_lookup(&id, &*self.find, self.cache, &mut self.buf)?;
296+
let commit = match res {
297+
None => return Ok(None),
298+
Some(commit) => commit,
299+
};
300+
let mut commit = commit.to_owned(T::default)?;
301+
update_commit(&mut commit, false);
302+
entry.insert(commit);
303+
}
304+
gix_hashtable::hash_map::Entry::Occupied(mut entry) => {
305+
update_commit(entry.get_mut(), true);
306+
}
307+
};
308+
Ok(self.map.get_mut(&id))
309+
}
282310
}
283311

284312
/// Lazy commit access

0 commit comments

Comments
 (0)