Skip to content

Commit bd08124

Browse files
committed
feat!: Graph now borrows the commitgraph cache.
That way, operations that need a commit-graph (graph data structure) can be run more efficiently as they won't consume the graph, but can reuse it.
1 parent 5f40135 commit bd08124

File tree

3 files changed

+36
-35
lines changed

3 files changed

+36
-35
lines changed

gix-revwalk/src/graph/commit.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ use smallvec::SmallVec;
44
use super::LazyCommit;
55
use crate::graph::{Commit, Either, Generation};
66

7-
impl<'graph> LazyCommit<'graph> {
7+
impl<'graph, 'cache> LazyCommit<'graph, 'cache> {
88
/// Return an iterator over the parents of this commit.
9-
pub fn iter_parents(&self) -> Parents<'graph> {
9+
pub fn iter_parents(&self) -> Parents<'graph, 'cache> {
1010
let backing = match &self.backing {
1111
Either::Left(buf) => Either::Left(gix_object::CommitRefIter::from_bytes(buf)),
1212
Either::Right((cache, pos)) => Either::Right((*cache, cache.commit_at(*pos).iter_parents())),
@@ -89,17 +89,17 @@ impl<'graph> LazyCommit<'graph> {
8989
}
9090

9191
/// An iterator over the parents of a commit.
92-
pub struct Parents<'graph> {
92+
pub struct Parents<'graph, 'cache> {
9393
backing: Either<
9494
gix_object::CommitRefIter<'graph>,
9595
(
96-
&'graph gix_commitgraph::Graph,
97-
gix_commitgraph::file::commit::Parents<'graph>,
96+
&'cache gix_commitgraph::Graph,
97+
gix_commitgraph::file::commit::Parents<'cache>,
9898
),
9999
>,
100100
}
101101

102-
impl<'graph> Iterator for Parents<'graph> {
102+
impl<'graph, 'cache> Iterator for Parents<'graph, 'cache> {
103103
type Item = Result<gix_hash::ObjectId, iter_parents::Error>;
104104

105105
fn next(&mut self) -> Option<Self::Item> {

gix-revwalk/src/graph/mod.rs

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ use gix_date::SecondsSinceUnixEpoch;
5353
/// This number is only available natively if there is a commit-graph.
5454
pub type Generation = u32;
5555

56-
impl<'find, T: std::fmt::Debug> std::fmt::Debug for Graph<'find, T> {
56+
impl<'find, 'cache, T: std::fmt::Debug> std::fmt::Debug for Graph<'find, 'cache, T> {
5757
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5858
std::fmt::Debug::fmt(&self.map, f)
5959
}
6060
}
6161

62-
impl<'find, T: Default> Graph<'find, T> {
62+
impl<'find, 'cache, T: Default> Graph<'find, 'cache, T> {
6363
/// Lookup `id` without failing if the commit doesn't exist, and assure that `id` is inserted into our set.
6464
/// If it wasn't, associate it with the default value. Assure `update_data(data)` gets run.
6565
/// Return the commit when done.
@@ -68,13 +68,13 @@ impl<'find, T: Default> Graph<'find, T> {
6868
&mut self,
6969
id: gix_hash::ObjectId,
7070
update_data: impl FnOnce(&mut T),
71-
) -> Result<Option<LazyCommit<'_>>, try_lookup_or_insert_default::Error> {
71+
) -> Result<Option<LazyCommit<'_, 'cache>>, try_lookup_or_insert_default::Error> {
7272
self.try_lookup_or_insert_default(id, T::default, update_data)
7373
}
7474
}
7575

7676
/// Access and mutation
77-
impl<'find, T> Graph<'find, T> {
77+
impl<'find, 'cache, T> Graph<'find, 'cache, T> {
7878
/// Returns true if `id` has data associated with it, meaning that we processed it already.
7979
pub fn contains(&self, id: &gix_hash::oid) -> bool {
8080
self.map.contains_key(id.as_ref())
@@ -101,7 +101,7 @@ impl<'find, T> Graph<'find, T> {
101101
pub fn insert_data<E>(
102102
&mut self,
103103
id: gix_hash::ObjectId,
104-
mut make_data: impl FnMut(LazyCommit<'_>) -> Result<T, E>,
104+
mut make_data: impl FnMut(LazyCommit<'_, 'cache>) -> Result<T, E>,
105105
) -> Result<Option<T>, E>
106106
where
107107
E: From<gix_object::find::existing_iter::Error>,
@@ -132,7 +132,7 @@ impl<'find, T> Graph<'find, T> {
132132
let parent_id = parent_id?;
133133
match self.map.entry(parent_id) {
134134
gix_hashtable::hash_map::Entry::Vacant(entry) => {
135-
let parent = match try_lookup(&parent_id, &*self.find, self.cache.as_ref(), &mut self.parent_buf)? {
135+
let parent = match try_lookup(&parent_id, &*self.find, self.cache, &mut self.parent_buf)? {
136136
Some(p) => p,
137137
None => continue, // skip missing objects, this is due to shallow clones for instance.
138138
};
@@ -160,7 +160,7 @@ impl<'find, T> Graph<'find, T> {
160160
pub fn insert_parents_with_lookup<E>(
161161
&mut self,
162162
id: &gix_hash::oid,
163-
parent_data: &mut dyn FnMut(gix_hash::ObjectId, LazyCommit<'_>, Option<&mut T>) -> Result<T, E>,
163+
parent_data: &mut dyn FnMut(gix_hash::ObjectId, LazyCommit<'_, 'cache>, Option<&mut T>) -> Result<T, E>,
164164
) -> Result<(), E>
165165
where
166166
E: From<gix_object::find::existing_iter::Error>
@@ -171,9 +171,7 @@ impl<'find, T> Graph<'find, T> {
171171
let parents: SmallVec<[_; 2]> = commit.iter_parents().collect();
172172
for parent_id in parents {
173173
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-
{
174+
let parent = match try_lookup(&parent_id, &*self.find, self.cache, &mut self.parent_buf).map_err(E::from)? {
177175
Some(p) => p,
178176
None => continue, // skip missing objects, this is due to shallow clones for instance.
179177
};
@@ -197,7 +195,7 @@ impl<'find, T> Graph<'find, T> {
197195
}
198196

199197
/// Initialization
200-
impl<'find, T> Graph<'find, T> {
198+
impl<'find, 'cache, T> Graph<'find, 'cache, T> {
201199
/// Create a new instance with `objects` to retrieve commits and optionally `cache` to accelerate commit access.
202200
///
203201
/// ### Performance
@@ -206,7 +204,7 @@ impl<'find, T> Graph<'find, T> {
206204
/// most recently used commits.
207205
/// Furthermore, **none-existing commits should not trigger the pack-db to be refreshed.** Otherwise, performance may be sub-optimal
208206
/// in shallow repositories as running into non-existing commits will trigger a refresh of the `packs` directory.
209-
pub fn new(objects: impl gix_object::Find + 'find, cache: impl Into<Option<gix_commitgraph::Graph>>) -> Self {
207+
pub fn new(objects: impl gix_object::Find + 'find, cache: Option<&'cache gix_commitgraph::Graph>) -> Self {
210208
Graph {
211209
find: Box::new(objects),
212210
cache: cache.into(),
@@ -218,7 +216,7 @@ impl<'find, T> Graph<'find, T> {
218216
}
219217

220218
/// commit access
221-
impl<'find, T> Graph<'find, Commit<T>> {
219+
impl<'find, 'cache, T> Graph<'find, 'cache, Commit<T>> {
222220
/// Lookup `id` without failing if the commit doesn't exist, and assure that `id` is inserted into our set
223221
/// with a commit with `new_data()` assigned.
224222
/// `update_data(data)` gets run either on existing or on new data.
@@ -232,7 +230,7 @@ impl<'find, T> Graph<'find, Commit<T>> {
232230
) -> Result<Option<&mut Commit<T>>, try_lookup_or_insert_default::Error> {
233231
match self.map.entry(id) {
234232
gix_hashtable::hash_map::Entry::Vacant(entry) => {
235-
let res = try_lookup(&id, &*self.find, self.cache.as_ref(), &mut self.buf)?;
233+
let res = try_lookup(&id, &*self.find, self.cache, &mut self.buf)?;
236234
let commit = match res {
237235
None => return Ok(None),
238236
Some(commit) => commit,
@@ -250,7 +248,7 @@ impl<'find, T> Graph<'find, Commit<T>> {
250248
}
251249

252250
/// commit access
253-
impl<'find, T: Default> Graph<'find, Commit<T>> {
251+
impl<'find, 'cache, T: Default> Graph<'find, 'cache, Commit<T>> {
254252
/// Lookup `id` without failing if the commit doesn't exist or `id` isn't a commit,
255253
/// and assure that `id` is inserted into our set with a commit and default data assigned.
256254
/// `update_data(data)` gets run either on existing or on new data.
@@ -269,7 +267,7 @@ impl<'find, T: Default> Graph<'find, Commit<T>> {
269267
}
270268

271269
/// Lazy commit access
272-
impl<'find, T> Graph<'find, T> {
270+
impl<'find, 'cache, T> Graph<'find, 'cache, T> {
273271
/// Lookup `id` without failing if the commit doesn't exist or `id` isn't a commit,
274272
/// and assure that `id` is inserted into our set
275273
/// with a `default` value assigned to it.
@@ -285,8 +283,8 @@ impl<'find, T> Graph<'find, T> {
285283
id: gix_hash::ObjectId,
286284
default: impl FnOnce() -> T,
287285
update_data: impl FnOnce(&mut T),
288-
) -> Result<Option<LazyCommit<'_>>, try_lookup_or_insert_default::Error> {
289-
let res = try_lookup(&id, &*self.find, self.cache.as_ref(), &mut self.buf)?;
286+
) -> Result<Option<LazyCommit<'_, 'cache>>, try_lookup_or_insert_default::Error> {
287+
let res = try_lookup(&id, &*self.find, self.cache, &mut self.buf)?;
290288
Ok(res.map(|commit| {
291289
match self.map.entry(id) {
292290
gix_hashtable::hash_map::Entry::Vacant(entry) => {
@@ -309,23 +307,26 @@ impl<'find, T> Graph<'find, T> {
309307
pub fn try_lookup(
310308
&mut self,
311309
id: &gix_hash::oid,
312-
) -> Result<Option<LazyCommit<'_>>, gix_object::find::existing_iter::Error> {
313-
try_lookup(id, &*self.find, self.cache.as_ref(), &mut self.buf)
310+
) -> Result<Option<LazyCommit<'_, 'cache>>, gix_object::find::existing_iter::Error> {
311+
try_lookup(id, &*self.find, self.cache, &mut self.buf)
314312
}
315313

316314
/// Lookup `id` and return a handle to it, or fail if it doesn't exist or is no commit.
317-
pub fn lookup(&mut self, id: &gix_hash::oid) -> Result<LazyCommit<'_>, gix_object::find::existing_iter::Error> {
315+
pub fn lookup(
316+
&mut self,
317+
id: &gix_hash::oid,
318+
) -> Result<LazyCommit<'_, 'cache>, gix_object::find::existing_iter::Error> {
318319
self.try_lookup(id)?
319320
.ok_or(gix_object::find::existing_iter::Error::NotFound { oid: id.to_owned() })
320321
}
321322
}
322323

323-
fn try_lookup<'graph>(
324+
fn try_lookup<'graph, 'cache>(
324325
id: &gix_hash::oid,
325326
objects: &dyn gix_object::Find,
326-
cache: Option<&'graph gix_commitgraph::Graph>,
327+
cache: Option<&'cache gix_commitgraph::Graph>,
327328
buf: &'graph mut Vec<u8>,
328-
) -> Result<Option<LazyCommit<'graph>>, gix_object::find::existing_iter::Error> {
329+
) -> Result<Option<LazyCommit<'graph, 'cache>>, gix_object::find::existing_iter::Error> {
329330
if let Some(cache) = cache {
330331
if let Some(pos) = cache.lookup(id) {
331332
return Ok(Some(LazyCommit {
@@ -347,7 +348,7 @@ fn try_lookup<'graph>(
347348
)
348349
}
349350

350-
impl<'a, 'find, T> Index<&'a gix_hash::oid> for Graph<'find, T> {
351+
impl<'a, 'find, 'cache, T> Index<&'a gix_hash::oid> for Graph<'find, 'cache, T> {
351352
type Output = T;
352353

353354
fn index(&self, index: &'a oid) -> &Self::Output {
@@ -398,8 +399,8 @@ where
398399
/// A commit that provides access to graph-related information, on demand.
399400
///
400401
/// The owned version of this type is called [`Commit`] and can be obtained by calling [`LazyCommit::to_owned()`].
401-
pub struct LazyCommit<'graph> {
402-
backing: Either<&'graph [u8], (&'graph gix_commitgraph::Graph, gix_commitgraph::Position)>,
402+
pub struct LazyCommit<'graph, 'cache> {
403+
backing: Either<&'graph [u8], (&'cache gix_commitgraph::Graph, gix_commitgraph::Position)>,
403404
}
404405

405406
enum Either<T, U> {

gix-revwalk/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525
///
2626
/// Additionally, and only if `T` is [`Commit<T>`][graph::Commit], there is *no need for an object cache* as we keep track of
2727
/// everything related to commit traversal in our own hashmap.
28-
pub struct Graph<'find, T> {
28+
pub struct Graph<'find, 'cache, T> {
2929
/// A way to resolve a commit from the object database.
3030
find: Box<dyn gix_object::Find + 'find>,
3131
/// A way to speedup commit access, essentially a multi-file commit database.
32-
cache: Option<gix_commitgraph::Graph>,
32+
cache: Option<&'cache gix_commitgraph::Graph>,
3333
/// The set of cached commits that we have seen once, along with data associated with them.
3434
map: graph::IdMap<T>,
3535
/// A buffer for writing commit data into.

0 commit comments

Comments
 (0)