summaryrefslogtreecommitdiffstats
path: root/vendor/gix/src/revision
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/gix/src/revision
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-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.rs11
-rw-r--r--vendor/gix/src/revision/walk.rs102
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)))
}
}
}