Skip to content

Commit a884121

Browse files
committed
Merge branch 'fix-801'
2 parents 61eec5a + ec93f75 commit a884121

File tree

3 files changed

+68
-22
lines changed

3 files changed

+68
-22
lines changed

gix-traverse/src/commit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl Default for Parents {
2323
}
2424

2525
/// Specify how to sort commits during traversal.
26-
#[derive(Copy, Clone)]
26+
#[derive(Debug, Copy, Clone)]
2727
pub enum Sorting {
2828
/// Commits are sorted as they are mentioned in the commit graph.
2929
Topological,

gix/src/revision/walk.rs

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,14 @@ impl<'repo> Platform<'repo> {
5050

5151
/// Produce the iterator
5252
impl<'repo> Platform<'repo> {
53-
/// Return an iterator to traverse all commits reachable as configured by the [Platform].
54-
///
55-
/// # Performance
53+
/// For each commit, let `filter` return `true` if it and its parents should be included in the traversal, or `false`
54+
/// if the traversal should exclude it and its ancestry entirely.
5655
///
57-
/// It's highly recommended to set an [`object cache`][Repository::object_cache_size()] on the parent repo
58-
/// to greatly speed up performance if the returned id is supposed to be looked up right after.
59-
pub fn all(self) -> Result<revision::Walk<'repo>, Error> {
56+
/// If `filter` is None, no pruning of the graph will be performed which is the default.
57+
pub fn selected(
58+
self,
59+
mut filter: impl FnMut(&gix_hash::oid) -> bool + 'repo,
60+
) -> Result<revision::Walk<'repo>, Error> {
6061
let Platform {
6162
repo,
6263
tips,
@@ -74,22 +75,27 @@ impl<'repo> Platform<'repo> {
7475
let shallow_commits = repo.shallow_commits()?;
7576
let mut grafted_parents_to_skip = Vec::new();
7677
let mut buf = Vec::new();
77-
move |id| match shallow_commits.as_ref() {
78-
Some(commits) => {
79-
let id = id.to_owned();
80-
if let Ok(idx) = grafted_parents_to_skip.binary_search(&id) {
81-
grafted_parents_to_skip.remove(idx);
82-
return false;
83-
};
84-
if commits.binary_search(&id).is_ok() {
85-
if let Ok(commit) = repo.objects.find_commit_iter(id, &mut buf) {
86-
grafted_parents_to_skip.extend(commit.parent_ids());
87-
grafted_parents_to_skip.sort();
88-
}
89-
};
90-
true
78+
move |id| {
79+
if !filter(id) {
80+
return false;
81+
}
82+
match shallow_commits.as_ref() {
83+
Some(commits) => {
84+
let id = id.to_owned();
85+
if let Ok(idx) = grafted_parents_to_skip.binary_search(&id) {
86+
grafted_parents_to_skip.remove(idx);
87+
return false;
88+
};
89+
if commits.binary_search(&id).is_ok() {
90+
if let Ok(commit) = repo.objects.find_commit_iter(id, &mut buf) {
91+
grafted_parents_to_skip.extend(commit.parent_ids());
92+
grafted_parents_to_skip.sort();
93+
}
94+
};
95+
true
96+
}
97+
None => true,
9198
}
92-
None => true,
9399
}
94100
},
95101
)
@@ -98,6 +104,15 @@ impl<'repo> Platform<'repo> {
98104
),
99105
})
100106
}
107+
/// Return an iterator to traverse all commits reachable as configured by the [Platform].
108+
///
109+
/// # Performance
110+
///
111+
/// It's highly recommended to set an [`object cache`][Repository::object_cache_size()] on the parent repo
112+
/// to greatly speed up performance if the returned id is supposed to be looked up right after.
113+
pub fn all(self) -> Result<revision::Walk<'repo>, Error> {
114+
self.selected(|_| true)
115+
}
101116
}
102117

103118
pub(crate) mod iter {

gix/tests/id/mod.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ fn display_and_debug() -> crate::Result {
6767
}
6868

6969
mod ancestors {
70+
use crate::id::hex_to_id;
7071
use gix_traverse::commit;
7172

7273
#[test]
@@ -98,4 +99,34 @@ mod ancestors {
9899
);
99100
Ok(())
100101
}
102+
103+
#[test]
104+
fn filtered() -> crate::Result {
105+
let repo = crate::repo("make_repo_with_fork_and_dates.sh")?.to_thread_local();
106+
let head = repo.head()?.into_fully_peeled_id().expect("born")?;
107+
108+
for sorting in [
109+
commit::Sorting::Topological,
110+
commit::Sorting::ByCommitTimeNewestFirst,
111+
commit::Sorting::ByCommitTimeNewestFirstCutoffOlderThan {
112+
time_in_seconds_since_epoch: 0,
113+
},
114+
] {
115+
let commits_graph_order = head
116+
.ancestors()
117+
.sorting(sorting)
118+
.selected(|id| {
119+
let _assert_lifetime_works = &repo; // assure we can use repo here.
120+
id != hex_to_id("9902e3c3e8f0c569b4ab295ddf473e6de763e1e7")
121+
&& id != hex_to_id("bcb05040a6925f2ff5e10d3ae1f9264f2e8c43ac")
122+
})?
123+
.collect::<Result<Vec<_>, _>>()?;
124+
assert_eq!(
125+
commits_graph_order,
126+
&[hex_to_id("288e509293165cb5630d08f4185bdf2445bf6170")],
127+
"we ignore all but the first"
128+
);
129+
}
130+
Ok(())
131+
}
101132
}

0 commit comments

Comments
 (0)