diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
commit | 837b550238aa671a591ccf282dddeab29cadb206 (patch) | |
tree | 914b6b8862bace72bd3245ca184d374b08d8a672 /vendor/gix/src/revision/walk.rs | |
parent | Adding debian version 1.70.0+dfsg2-1. (diff) | |
download | rustc-837b550238aa671a591ccf282dddeab29cadb206.tar.xz rustc-837b550238aa671a591ccf282dddeab29cadb206.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix/src/revision/walk.rs')
-rw-r--r-- | vendor/gix/src/revision/walk.rs | 102 |
1 files changed, 55 insertions, 47 deletions
diff --git a/vendor/gix/src/revision/walk.rs b/vendor/gix/src/revision/walk.rs index 5b04b43a7..9c545d0d4 100644 --- a/vendor/gix/src/revision/walk.rs +++ b/vendor/gix/src/revision/walk.rs @@ -3,6 +3,16 @@ use gix_odb::FindExt; use crate::{revision, Repository}; +/// The error returned by [`Platform::all()`]. +#[derive(Debug, thiserror::Error)] +#[allow(missing_docs)] +pub enum Error { + #[error(transparent)] + AncestorIter(#[from] gix_traverse::commit::ancestors::Error), + #[error(transparent)] + ShallowCommits(#[from] crate::shallow::open::Error), +} + /// A platform to traverse the revision graph by adding starting points as well as points which shouldn't be crossed, /// returned by [`Repository::rev_walk()`]. pub struct Platform<'repo> { @@ -40,13 +50,14 @@ impl<'repo> Platform<'repo> { /// Produce the iterator impl<'repo> Platform<'repo> { - /// Return an iterator to traverse all commits reachable as configured by the [Platform]. - /// - /// # Performance + /// For each commit, let `filter` return `true` if it and its parents should be included in the traversal, or `false` + /// if the traversal should exclude it and its ancestry entirely. /// - /// It's highly recommended to set an [`object cache`][Repository::object_cache_size()] on the parent repo - /// to greatly speed up performance if the returned id is supposed to be looked up right after. - pub fn all(self) -> Result<revision::Walk<'repo>, gix_traverse::commit::ancestors::Error> { + /// If `filter` is None, no pruning of the graph will be performed which is the default. + pub fn selected( + self, + mut filter: impl FnMut(&gix_hash::oid) -> bool + 'repo, + ) -> Result<revision::Walk<'repo>, Error> { let Platform { repo, tips, @@ -56,18 +67,52 @@ impl<'repo> Platform<'repo> { Ok(revision::Walk { repo, inner: Box::new( - gix_traverse::commit::Ancestors::new( + gix_traverse::commit::Ancestors::filtered( tips, gix_traverse::commit::ancestors::State::default(), move |oid, buf| repo.objects.find_commit_iter(oid, buf), + { + let shallow_commits = repo.shallow_commits()?; + let mut grafted_parents_to_skip = Vec::new(); + let mut buf = Vec::new(); + move |id| { + if !filter(id) { + return false; + } + match shallow_commits.as_ref() { + Some(commits) => { + let id = id.to_owned(); + if let Ok(idx) = grafted_parents_to_skip.binary_search(&id) { + grafted_parents_to_skip.remove(idx); + return false; + }; + if commits.binary_search(&id).is_ok() { + if let Ok(commit) = repo.objects.find_commit_iter(id, &mut buf) { + grafted_parents_to_skip.extend(commit.parent_ids()); + grafted_parents_to_skip.sort(); + } + }; + true + } + None => true, + } + } + }, ) .sorting(sorting)? .parents(parents), ), - is_shallow: None, - error_on_missing_commit: false, }) } + /// Return an iterator to traverse all commits reachable as configured by the [Platform]. + /// + /// # Performance + /// + /// It's highly recommended to set an [`object cache`][Repository::object_cache_size()] on the parent repo + /// to greatly speed up performance if the returned id is supposed to be looked up right after. + pub fn all(self) -> Result<revision::Walk<'repo>, Error> { + self.selected(|_| true) + } } pub(crate) mod iter { @@ -78,50 +123,13 @@ pub(crate) mod iter { pub(crate) repo: &'repo crate::Repository, pub(crate) inner: Box<dyn Iterator<Item = Result<gix_hash::ObjectId, gix_traverse::commit::ancestors::Error>> + 'repo>, - pub(crate) error_on_missing_commit: bool, - // TODO: tests - /// After iteration this flag is true if the iteration was stopped prematurely due to missing parent commits. - /// Note that this flag won't be `Some` if any iteration error occurs, which is the case if - /// [`error_on_missing_commit()`][Walk::error_on_missing_commit()] was called. - /// - /// This happens if a repository is a shallow clone. - /// Note that this value is `None` as long as the iteration isn't complete. - pub is_shallow: Option<bool>, - } - - impl<'repo> Walk<'repo> { - // TODO: tests - /// Once invoked, the iteration will return an error if a commit cannot be found in the object database. This typically happens - /// when operating on a shallow clone and thus is non-critical by default. - /// - /// Check the [`is_shallow`][Walk::is_shallow] field once the iteration ended otherwise to learn if a shallow commit graph - /// was encountered. - pub fn error_on_missing_commit(mut self) -> Self { - self.error_on_missing_commit = true; - self - } } impl<'repo> Iterator for Walk<'repo> { type Item = Result<Id<'repo>, gix_traverse::commit::ancestors::Error>; fn next(&mut self) -> Option<Self::Item> { - match self.inner.next() { - None => { - self.is_shallow = Some(false); - None - } - Some(Ok(oid)) => Some(Ok(oid.attach(self.repo))), - Some(Err(err @ gix_traverse::commit::ancestors::Error::FindExisting { .. })) => { - if self.error_on_missing_commit { - Some(Err(err)) - } else { - self.is_shallow = Some(true); - None - } - } - Some(Err(err)) => Some(Err(err)), - } + self.inner.next().map(|res| res.map(|id| id.attach(self.repo))) } } } |