Makes it easier to use these types for different kinds of commit walking. No matter how the history graph is traversed some concepts remain identical.
Unified · Split
| @@ -1,4 +1,3 @@ | |||
| 1 | use gix_object::FindExt; | ||
| 2 | use smallvec::SmallVec; | 1 | use smallvec::SmallVec; |
| 3 | 2 | ||
| 4 | /// An iterator over the ancestors one or more starting commits | 3 | /// An iterator over the ancestors one or more starting commits |
| @@ -7,20 +6,10 @@ pub struct Ancestors<Find, Predicate, StateMut> { · 2 unmodified lines | |||
| 7 | cache: Option<gix_commitgraph::Graph>, | 6 | cache: Option<gix_commitgraph::Graph>, |
| 8 | predicate: Predicate, | 7 | predicate: Predicate, |
| 9 | state: StateMut, | 8 | state: StateMut, |
| 10 | parents: Parents, | 9 | parents: super::Parents, |
| 11 | sorting: Sorting, | 10 | sorting: Sorting, |
| 12 | } | 11 | } |
| 13 | 12 | ||
| 14 | /// Specify how to handle commit parents during traversal. | ||
| 15 | #[derive(Default, Copy, Clone)] | ||
| 16 | pub enum Parents { | ||
| 17 | /// Traverse all parents, useful for traversing the entire ancestry. | ||
| 18 | #[default] | ||
| 19 | All, | ||
| 20 | /// Only traverse along the first parent, which commonly ignores all branches. | ||
| 21 | First, | ||
| 22 | } | ||
| 23 | |||
| 24 | /// Specify how to sort commits during traversal. | 13 | /// Specify how to sort commits during traversal. |
| 25 | /// | 14 | /// |
| 26 | /// ### Sample History | 15 | /// ### Sample History |
| @@ -69,23 +58,6 @@ pub enum Sorting { · 42 unmodified lines | |||
| 69 | }, | 58 | }, |
| 70 | } | 59 | } |
| 71 | 60 | ||
| 72 | /// The collection of parent ids we saw as part of the iteration. | ||
| 73 | /// | ||
| 74 | /// Note that this list is truncated if [`Parents::First`] was used. | ||
| 75 | pub type ParentIds = SmallVec<[gix_hash::ObjectId; 1]>; | ||
| 76 | |||
| 77 | /// Information about a commit that we obtained naturally as part of the iteration. | ||
| 78 | #[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)] | ||
| 79 | pub struct Info { | ||
| 80 | /// The id of the commit. | ||
| 81 | pub id: gix_hash::ObjectId, | ||
| 82 | /// All parent ids we have encountered. Note that these will be at most one if [`Parents::First`] is enabled. | ||
| 83 | pub parent_ids: ParentIds, | ||
| 84 | /// The time at which the commit was created. It's only `Some(_)` if sorting is not [`Sorting::BreadthFirst`], as the walk | ||
| 85 | /// needs to require the commit-date. | ||
| 86 | pub commit_time: Option<gix_date::SecondsSinceUnixEpoch>, | ||
| 87 | } | ||
| 88 | |||
| 89 | /// | 61 | /// |
| 90 | #[allow(clippy::empty_docs)] | 62 | #[allow(clippy::empty_docs)] |
| 91 | pub mod ancestors { | 63 | pub mod ancestors { |
| @@ -100,7 +72,10 @@ pub mod ancestors { · 8 unmodified lines | |||
| 100 | use gix_object::{CommitRefIter, FindExt}; | 72 | use gix_object::{CommitRefIter, FindExt}; |
| 101 | use smallvec::SmallVec; | 73 | use smallvec::SmallVec; |
| 102 | 74 | ||
| 103 | use super::{collect_parents, Ancestors, Either, Info, ParentIds, Parents, Sorting}; | 75 | use super::{ |
| 76 | super::{Either, Info, ParentIds, Parents}, | ||
| 77 | collect_parents, Ancestors, Sorting, | ||
| 78 | }; | ||
| 104 | 79 | ||
| 105 | /// The error is part of the item returned by the [Ancestors] iterator. | 80 | /// The error is part of the item returned by the [Ancestors] iterator. |
| 106 | #[derive(Debug, thiserror::Error)] | 81 | #[derive(Debug, thiserror::Error)] |
| @@ -339,7 +314,7 @@ pub mod ancestors { · 232 unmodified lines | |||
| 339 | 314 | ||
| 340 | let (commit_time, oid) = state.queue.pop()?; | 315 | let (commit_time, oid) = state.queue.pop()?; |
| 341 | let mut parents: ParentIds = Default::default(); | 316 | let mut parents: ParentIds = Default::default(); |
| 342 | match super::find(self.cache.as_ref(), &self.objects, &oid, &mut state.buf) { | 317 | match super::super::find(self.cache.as_ref(), &self.objects, &oid, &mut state.buf) { |
| 343 | Ok(Either::CachedCommit(commit)) => { | 318 | Ok(Either::CachedCommit(commit)) => { |
| 344 | if !collect_parents(&mut state.parent_ids, self.cache.as_ref(), commit.iter_parents()) { | 319 | if !collect_parents(&mut state.parent_ids, self.cache.as_ref(), commit.iter_parents()) { |
| 345 | // drop corrupt caches and try again with ODB | 320 | // drop corrupt caches and try again with ODB |
| @@ -406,7 +381,7 @@ pub mod ancestors { · 60 unmodified lines | |||
| 406 | let state = self.state.borrow_mut(); | 381 | let state = self.state.borrow_mut(); |
| 407 | let oid = state.next.pop_front()?; | 382 | let oid = state.next.pop_front()?; |
| 408 | let mut parents: ParentIds = Default::default(); | 383 | let mut parents: ParentIds = Default::default(); |
| 409 | match super::find(self.cache.as_ref(), &self.objects, &oid, &mut state.buf) { | 384 | match super::super::find(self.cache.as_ref(), &self.objects, &oid, &mut state.buf) { |
| 410 | Ok(Either::CachedCommit(commit)) => { | 385 | Ok(Either::CachedCommit(commit)) => { |
| 411 | if !collect_parents(&mut state.parent_ids, self.cache.as_ref(), commit.iter_parents()) { | 386 | if !collect_parents(&mut state.parent_ids, self.cache.as_ref(), commit.iter_parents()) { |
| 412 | // drop corrupt caches and try again with ODB | 387 | // drop corrupt caches and try again with ODB |
| @@ -457,11 +432,6 @@ pub mod ancestors { · 44 unmodified lines | |||
| 457 | 432 | ||
| 458 | pub use ancestors::{Error, State}; | 433 | pub use ancestors::{Error, State}; |
| 459 | 434 | ||
| 460 | enum Either<'buf, 'cache> { | ||
| 461 | CommitRefIter(gix_object::CommitRefIter<'buf>), | ||
| 462 | CachedCommit(gix_commitgraph::file::Commit<'cache>), | ||
| 463 | } | ||
| 464 | |||
| 465 | fn collect_parents( | 435 | fn collect_parents( |
| 466 | dest: &mut SmallVec<[(gix_hash::ObjectId, gix_date::SecondsSinceUnixEpoch); 2]>, | 436 | dest: &mut SmallVec<[(gix_hash::ObjectId, gix_date::SecondsSinceUnixEpoch); 2]>, |
| 467 | cache: Option<&gix_commitgraph::Graph>, | 437 | cache: Option<&gix_commitgraph::Graph>, |
| @@ -483,18 +453,3 @@ fn collect_parents( · 15 unmodified lines | |||
| 483 | } | 453 | } |
| 484 | true | 454 | true |
| 485 | } | 455 | } |
| 486 | |||
| 487 | fn find<'cache, 'buf, Find>( | ||
| 488 | cache: Option<&'cache gix_commitgraph::Graph>, | ||
| 489 | objects: Find, | ||
| 490 | id: &gix_hash::oid, | ||
| 491 | buf: &'buf mut Vec<u8>, | ||
| 492 | ) -> Result<Either<'buf, 'cache>, gix_object::find::existing_iter::Error> | ||
| 493 | where | ||
| 494 | Find: gix_object::Find, | ||
| 495 | { | ||
| 496 | match cache.and_then(|cache| cache.commit_by_id(id).map(Either::CachedCommit)) { | ||
| 497 | Some(c) => Ok(c), | ||
| 498 | None => objects.find_commit_iter(id, buf).map(Either::CommitRefIter), | ||
| 499 | } | ||
| 500 | } | ||
| @@ -1,3 +1,53 @@ | |||
| 1 | use gix_object::FindExt; | ||
| 2 | use smallvec::SmallVec; | ||
| 3 | |||
| 1 | /// Simple ancestors traversal | 4 | /// Simple ancestors traversal |
| 2 | pub mod ancestors; | 5 | pub mod ancestors; |
| 3 | pub use ancestors::{Ancestors, Info, ParentIds, Parents, Sorting}; | 6 | pub use ancestors::{Ancestors, Sorting}; |
| 7 | |||
| 8 | /// Specify how to handle commit parents during traversal. | ||
| 9 | #[derive(Default, Copy, Clone)] | ||
| 10 | pub enum Parents { | ||
| 11 | /// Traverse all parents, useful for traversing the entire ancestry. | ||
| 12 | #[default] | ||
| 13 | All, | ||
| 14 | /// Only traverse along the first parent, which commonly ignores all branches. | ||
| 15 | First, | ||
| 16 | } | ||
| 17 | |||
| 18 | /// The collection of parent ids we saw as part of the iteration. | ||
| 19 | /// | ||
| 20 | /// Note that this list is truncated if [`Parents::First`] was used. | ||
| 21 | pub type ParentIds = SmallVec<[gix_hash::ObjectId; 1]>; | ||
| 22 | |||
| 23 | /// Information about a commit that we obtained naturally as part of the iteration. | ||
| 24 | #[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)] | ||
| 25 | pub struct Info { | ||
| 26 | /// The id of the commit. | ||
| 27 | pub id: gix_hash::ObjectId, | ||
| 28 | /// All parent ids we have encountered. Note that these will be at most one if [`Parents::First`] is enabled. | ||
| 29 | pub parent_ids: ParentIds, | ||
| 30 | /// The time at which the commit was created. It's only `Some(_)` if sorting is not [`Sorting::BreadthFirst`], as the walk | ||
| 31 | /// needs to require the commit-date. | ||
| 32 | pub commit_time: Option<gix_date::SecondsSinceUnixEpoch>, | ||
| 33 | } | ||
| 34 | |||
| 35 | enum Either<'buf, 'cache> { | ||
| 36 | CommitRefIter(gix_object::CommitRefIter<'buf>), | ||
| 37 | CachedCommit(gix_commitgraph::file::Commit<'cache>), | ||
| 38 | } | ||
| 39 | |||
| 40 | fn find<'cache, 'buf, Find>( | ||
| 41 | cache: Option<&'cache gix_commitgraph::Graph>, | ||
| 42 | objects: Find, | ||
| 43 | id: &gix_hash::oid, | ||
| 44 | buf: &'buf mut Vec<u8>, | ||
| 45 | ) -> Result<Either<'buf, 'cache>, gix_object::find::existing_iter::Error> | ||
| 46 | where | ||
| 47 | Find: gix_object::Find, | ||
| 48 | { | ||
| 49 | match cache.and_then(|cache| cache.commit_by_id(id).map(Either::CachedCommit)) { | ||
| 50 | Some(c) => Ok(c), | ||
| 51 | None => objects.find_commit_iter(id, buf).map(Either::CommitRefIter), | ||
| 52 | } | ||
| 53 | } | ||