Skip to content

Commit b590a9d

Browse files
committed
Merge branch 'add-topo-walk'
2 parents 45edd2e + 1cfeb11 commit b590a9d

File tree

36 files changed

+1643
-653
lines changed

36 files changed

+1643
-653
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/log.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use clap::Parser;
88
use gix::{
99
bstr::{BString, ByteSlice},
1010
date::time::format,
11-
traverse::commit::Sorting,
11+
traverse::commit::simple::Sorting,
1212
};
1313

1414
fn main() {

gitoxide-core/src/hours/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ where
175175
}
176176
commit_idx += 1;
177177
}
178-
Err(gix::traverse::commit::ancestors::Error::Find { .. }) => {
178+
Err(gix::traverse::commit::simple::Error::Find { .. }) => {
179179
is_shallow = true;
180180
break;
181181
}

gitoxide-core/src/pack/create.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ where
130130
.collect::<Result<Vec<_>, _>>()?;
131131
let handle = repo.objects.into_shared_arc().to_cache_arc();
132132
let iter = Box::new(
133-
traverse::commit::Ancestors::new(tips, traverse::commit::ancestors::State::default(), handle.clone())
133+
traverse::commit::Simple::new(tips, handle.clone())
134134
.map(|res| res.map_err(|err| Box::new(err) as Box<_>).map(|c| c.id))
135135
.inspect(move |_| progress.inc()),
136136
);
@@ -361,7 +361,7 @@ pub mod input_iteration {
361361
#[derive(Debug, thiserror::Error)]
362362
pub enum Error {
363363
#[error("input objects couldn't be iterated completely")]
364-
Iteration(#[from] traverse::commit::ancestors::Error),
364+
Iteration(#[from] traverse::commit::simple::Error),
365365
#[error("An error occurred while reading hashes from standard input")]
366366
InputLinesIo(#[from] std::io::Error),
367367
#[error("Could not decode hex hash provided on standard input")]

gitoxide-core/src/query/engine/update.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ pub fn update(
429429
break;
430430
}
431431
}
432-
Err(gix::traverse::commit::ancestors::Error::Find { .. }) => {
432+
Err(gix::traverse::commit::simple::Error::Find { .. }) => {
433433
writeln!(err, "shallow repository - commit history is truncated").ok();
434434
break;
435435
}

gitoxide-core/src/repository/commitgraph/list.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ pub(crate) mod function {
22
use std::{borrow::Cow, ffi::OsString};
33

44
use anyhow::{bail, Context};
5-
use gix::{prelude::ObjectIdExt, traverse::commit::Sorting};
5+
use gix::{prelude::ObjectIdExt, traverse::commit::simple::Sorting};
66

77
use crate::OutputFormat;
88

gitoxide-core/src/repository/revision/list.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub const PROGRESS_RANGE: std::ops::RangeInclusive<u8> = 0..=2;
1717

1818
pub(crate) mod function {
1919
use anyhow::{bail, Context};
20-
use gix::{hashtable::HashMap, traverse::commit::Sorting, Progress};
20+
use gix::{hashtable::HashMap, traverse::commit::simple::Sorting, Progress};
2121
use layout::{
2222
backends::svg::SVGWriter,
2323
core::{base::Orientation, geometry::Point, style::StyleAttr},

gix-config/src/file/impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl<'a> TryFrom<&'a BStr> for File<'a> {
4242

4343
impl From<File<'_>> for BString {
4444
fn from(c: File<'_>) -> Self {
45-
c.into()
45+
c.to_bstring()
4646
}
4747
}
4848

gix-config/src/parse/comment.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ impl Display for Comment<'_> {
3939

4040
impl From<Comment<'_>> for BString {
4141
fn from(c: Comment<'_>) -> Self {
42-
c.into()
42+
c.to_bstring()
4343
}
4444
}
4545

gix-config/src/parse/event.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl Display for Event<'_> {
7272

7373
impl From<Event<'_>> for BString {
7474
fn from(event: Event<'_>) -> Self {
75-
event.into()
75+
event.to_bstring()
7676
}
7777
}
7878

gix-config/src/parse/section/header.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl Display for Header<'_> {
145145

146146
impl From<Header<'_>> for BString {
147147
fn from(header: Header<'_>) -> Self {
148-
header.into()
148+
header.to_bstring()
149149
}
150150
}
151151

gix-diff/tests/tree/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,10 @@ mod changes {
129129
}
130130

131131
fn all_commits(db: &gix_odb::Handle) -> HashMap<String, ObjectId> {
132-
use gix_traverse::commit;
133132
let mut buf = Vec::new();
134133

135134
let head = head_of(db);
136-
commit::Ancestors::new(Some(head), commit::ancestors::State::default(), &db)
135+
gix_traverse::commit::Simple::new(Some(head), &db)
137136
.collect::<Result<Vec<_>, _>>()
138137
.expect("valid iteration")
139138
.into_iter()

gix-pack/src/cache/delta/from_offsets.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,14 @@ impl<T> Tree<T> {
5757
})?,
5858
);
5959

60-
let anticipated_num_objects = if let Some(num_objects) = data_sorted_by_offsets.size_hint().1 {
61-
progress.init(Some(num_objects), progress::count("objects"));
62-
num_objects
63-
} else {
64-
0
65-
};
60+
let anticipated_num_objects = data_sorted_by_offsets
61+
.size_hint()
62+
.1
63+
.map(|num_objects| {
64+
progress.init(Some(num_objects), progress::count("objects"));
65+
num_objects
66+
})
67+
.unwrap_or_default();
6668
let mut tree = Tree::with_capacity(anticipated_num_objects)?;
6769

6870
{

gix-pack/tests/pack/data/output/count_and_entries.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use gix_pack::data::{
99
output,
1010
output::{count, entry},
1111
};
12-
use gix_traverse::commit;
1312

1413
use crate::pack::{
1514
data::output::{db, DbKind},
@@ -241,7 +240,7 @@ fn traversals() -> crate::Result {
241240
.copied()
242241
{
243242
let head = hex_to_id("dfcb5e39ac6eb30179808bbab721e8a28ce1b52e");
244-
let mut commits = commit::Ancestors::new(Some(head), commit::ancestors::State::default(), db.clone())
243+
let mut commits = gix_traverse::commit::Simple::new(Some(head), db.clone())
245244
.map(Result::unwrap)
246245
.map(|c| c.id)
247246
.collect::<Vec<_>>();

gix-traverse/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ gix-revwalk = { version = "^0.13.0", path = "../gix-revwalk" }
2222
gix-commitgraph = { version = "^0.24.2", path = "../gix-commitgraph" }
2323
smallvec = "1.10.0"
2424
thiserror = "1.0.32"
25+
bitflags = "2"

gix-traverse/src/commit/mod.rs

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//! Provide multiple traversal implementations with different performance envelopes.
2+
//!
3+
//! Use [`Simple`] for fast walks that maintain minimal state, or [`Topo`] for a more elaborate traversal.
4+
use gix_hash::ObjectId;
5+
use gix_object::FindExt;
6+
use gix_revwalk::graph::IdMap;
7+
use gix_revwalk::PriorityQueue;
8+
use smallvec::SmallVec;
9+
10+
/// A fast iterator over the ancestors of one or more starting commits.
11+
pub struct Simple<Find, Predicate> {
12+
objects: Find,
13+
cache: Option<gix_commitgraph::Graph>,
14+
predicate: Predicate,
15+
state: simple::State,
16+
parents: Parents,
17+
sorting: simple::Sorting,
18+
}
19+
20+
/// Simple ancestors traversal, without the need to keep track of graph-state.
21+
pub mod simple;
22+
23+
/// A commit walker that walks in topographical order, like `git rev-list
24+
/// --topo-order` or `--date-order` depending on the chosen [`topo::Sorting`].
25+
///
26+
/// Instantiate with [`topo::Builder`].
27+
pub struct Topo<Find, Predicate> {
28+
commit_graph: Option<gix_commitgraph::Graph>,
29+
find: Find,
30+
predicate: Predicate,
31+
indegrees: IdMap<i32>,
32+
states: IdMap<topo::WalkFlags>,
33+
explore_queue: PriorityQueue<topo::iter::GenAndCommitTime, ObjectId>,
34+
indegree_queue: PriorityQueue<topo::iter::GenAndCommitTime, ObjectId>,
35+
topo_queue: topo::iter::Queue,
36+
parents: Parents,
37+
min_gen: u32,
38+
buf: Vec<u8>,
39+
}
40+
41+
pub mod topo;
42+
43+
/// Specify how to handle commit parents during traversal.
44+
#[derive(Default, Copy, Clone)]
45+
pub enum Parents {
46+
/// Traverse all parents, useful for traversing the entire ancestry.
47+
#[default]
48+
All,
49+
/// Only traverse along the first parent, which commonly ignores all branches.
50+
First,
51+
}
52+
53+
/// The collection of parent ids we saw as part of the iteration.
54+
///
55+
/// Note that this list is truncated if [`Parents::First`] was used.
56+
pub type ParentIds = SmallVec<[gix_hash::ObjectId; 1]>;
57+
58+
/// Information about a commit that we obtained naturally as part of the iteration.
59+
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
60+
pub struct Info {
61+
/// The id of the commit.
62+
pub id: gix_hash::ObjectId,
63+
/// All parent ids we have encountered. Note that these will be at most one if [`Parents::First`] is enabled.
64+
pub parent_ids: ParentIds,
65+
/// The time at which the commit was created. It will only be `Some(_)` if the chosen traversal was
66+
/// taking dates into consideration.
67+
pub commit_time: Option<gix_date::SecondsSinceUnixEpoch>,
68+
}
69+
70+
enum Either<'buf, 'cache> {
71+
CommitRefIter(gix_object::CommitRefIter<'buf>),
72+
CachedCommit(gix_commitgraph::file::Commit<'cache>),
73+
}
74+
75+
fn find<'cache, 'buf, Find>(
76+
cache: Option<&'cache gix_commitgraph::Graph>,
77+
objects: Find,
78+
id: &gix_hash::oid,
79+
buf: &'buf mut Vec<u8>,
80+
) -> Result<Either<'buf, 'cache>, gix_object::find::existing_iter::Error>
81+
where
82+
Find: gix_object::Find,
83+
{
84+
match cache.and_then(|cache| cache.commit_by_id(id).map(Either::CachedCommit)) {
85+
Some(c) => Ok(c),
86+
None => objects.find_commit_iter(id, buf).map(Either::CommitRefIter),
87+
}
88+
}

0 commit comments

Comments
 (0)