diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/gix/src/revision | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.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')
-rw-r--r-- | vendor/gix/src/revision/spec/parse/types.rs | 11 | ||||
-rw-r--r-- | vendor/gix/src/revision/walk.rs | 102 |
2 files changed, 59 insertions, 54 deletions
diff --git a/vendor/gix/src/revision/spec/parse/types.rs b/vendor/gix/src/revision/spec/parse/types.rs index 4e523ab14..d852c297e 100644 --- a/vendor/gix/src/revision/spec/parse/types.rs +++ b/vendor/gix/src/revision/spec/parse/types.rs @@ -1,7 +1,7 @@ use crate::{bstr::BString, object, reference}; /// A hint to know what to do if refs and object names are equal. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] pub enum RefsHint { /// This is the default, and leads to specs that look like objects identified by full hex sha and are objects to be used /// instead of similarly named references. The latter is not typical but can absolutely happen by accident. @@ -9,6 +9,7 @@ pub enum RefsHint { /// preferred as there are many valid object names like `beef` and `cafe` that are short and both valid and typical prefixes /// for objects. /// Git chooses this as default as well, even though it means that every object prefix is also looked up as ref. + #[default] PreferObjectOnFullLengthHexShaUseRefOtherwise, /// No matter what, if it looks like an object prefix and has an object, use it. /// Note that no ref-lookup is made here which is the fastest option. @@ -38,12 +39,6 @@ pub enum ObjectKindHint { Blob, } -impl Default for RefsHint { - fn default() -> Self { - RefsHint::PreferObjectOnFullLengthHexShaUseRefOtherwise - } -} - /// Options for use in [`revision::Spec::from_bstr()`][crate::revision::Spec::from_bstr()]. #[derive(Debug, Default, Copy, Clone)] pub struct Options { @@ -177,6 +172,8 @@ pub enum Error { }, #[error(transparent)] Traverse(#[from] gix_traverse::commit::ancestors::Error), + #[error(transparent)] + Walk(#[from] crate::revision::walk::Error), #[error("Spec does not contain a single object id")] SingleNotFound, } 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))) } } } |