1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! Revision walking trait.
//!
//! # Architecture
//! This module provides the contract for traversing the commit graph. Walking
//! history is a fundamental operation for log generation, bisecting, and ancestry
//! queries. By abstracting this into a trait, the crate allows backends to implement
//! optimized traversal algorithms (e.g., topological sorting, priority queues based
//! on timestamps) without leaking those implementation details to the caller.
//!
//! # Design Rationale: Lazy Evaluation
//! Repositories like the Linux kernel contain millions of commits. Loading the
//! entire commit graph into memory at once would cause severe memory exhaustion.
//! The [`RevWalk::walk`] method returns an iterator, enforcing lazy evaluation.
//! Commits are only loaded and yielded from the underlying object store as the
//! iterator is consumed, maintaining a constant, predictable memory footprint.
use crateVctrlError;
/// An iterator over commit history.
///
/// # Why this exists
/// This type alias standardizes the return type of revision walks across all
/// backends. It uses dynamic dispatch (`Box<dyn Iterator>`) to perform type erasure.
/// This allows a backend to return any complex internal iterator struct (e.g., a
/// binary heap for priority-ordered traversal) without forcing the caller to know
/// the concrete type or bloating the trait signature with associated types.
///
/// # How it works
/// - `Item = Result<T, VctrlError>`: Yields a `Result` because graph traversal may
/// encounter I/O errors (e.g., a missing commit object) mid-iteration.
/// - `Send`: The iterator can be safely transferred across threads, enabling
/// parallel processing of commit history (e.g., using `rayon`).
/// - `'a`: The lifetime ties the iterator to the lifetime of the [`RevWalk`]
/// instance that created it, ensuring the backend store remains valid while
/// the iterator is active.
pub type RevWalkIterator<'a, T> = ;
/// Trait for walking commit history.
///
/// # Why this exists
/// Provides a unified interface for commit graph traversal. By using an associated
/// type for the commit identifier, the trait is not hardcoded to cryptographic
/// hashes. An in-memory testing backend might use array indices (`usize`), while
/// a disk-backed backend uses [`Hash`](crate::Hash).
///
/// # How it works
/// The `walk` method accepts a starting commit identifier and returns a
/// [`RevWalkIterator`]. The implementor is responsible for resolving the start
/// commit, reading its parent hashes, and pushing them into an internal queue.
/// As the caller calls `next()` on the iterator, the backend dequeues a commit,
/// fetches its parents, and yields the commit.
///
/// # Design Rationale: `&self` on `walk`
/// Note that `walk` takes `&self` instead of `&mut self`. Traversal is a read-only
/// operation from the perspective of the walker's state. The implementor must use
/// interior mutability (e.g., `Mutex` for internal buffers) if the underlying
/// object store requires mutable access to read objects, allowing multiple
/// concurrent walks to occur safely.
///
/// # Examples
///
/// Implementing the trait for a mock graph:
///
/// ```
/// # use libvctrl_handler::traits::core::revwalk::{RevWalk, RevWalkIterator};
/// # use libvctrl_handler::VctrlError;
/// #
/// struct MockRevWalk;
///
/// impl RevWalk for MockRevWalk {
/// type CommitId = u32;
///
/// fn walk(&self, start: &Self::CommitId) -> Result<RevWalkIterator<'_, Self::CommitId>, VctrlError> {
/// let start = *start;
/// // Simulate walking backwards through commit IDs 0 to `start`
/// Ok(Box::new((0..start).rev().map(Ok)))
/// }
/// }
///
/// let walker = MockRevWalk;
/// let iter = walker.walk(&3)?;
/// let commits: Vec<u32> = iter.filter_map(|c| c.ok()).collect();
/// assert_eq!(commits, vec![2, 1, 0]);
/// # Ok::<(), VctrlError>(())
/// ```