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
|
use crate::{file, file::Commit, File, Graph, Position};
/// Access
impl Graph {
/// Returns the commit at the given position `pos`.
///
/// # Panics
/// If `pos` is greater or equal to [`num_commits()`][Graph::num_commits()].
pub fn commit_at(&self, pos: Position) -> Commit<'_> {
let r = self.lookup_by_pos(pos);
r.file.commit_at(r.pos)
}
/// Returns the commit matching the given `id`.
pub fn commit_by_id(&self, id: impl AsRef<gix_hash::oid>) -> Option<Commit<'_>> {
let r = self.lookup_by_id(id.as_ref())?;
Some(r.file.commit_at(r.file_pos))
}
/// Returns the `hash` at the given position `pos`.
///
/// # Panics
/// If `pos` is greater or equal to [`num_commits()`][Graph::num_commits()].
pub fn id_at(&self, pos: Position) -> &gix_hash::oid {
let r = self.lookup_by_pos(pos);
r.file.id_at(r.pos)
}
/// Iterate over commits in unsorted order.
pub fn iter_commits(&self) -> impl Iterator<Item = Commit<'_>> {
self.files.iter().flat_map(|file| file.iter_commits())
}
/// Iterate over commit IDs in unsorted order.
pub fn iter_ids(&self) -> impl Iterator<Item = &gix_hash::oid> {
self.files.iter().flat_map(|file| file.iter_ids())
}
/// Translate the given `id` to its position in the file.
pub fn lookup(&self, id: impl AsRef<gix_hash::oid>) -> Option<Position> {
Some(self.lookup_by_id(id.as_ref())?.graph_pos)
}
/// Returns the number of commits stored in this file.
pub fn num_commits(&self) -> u32 {
self.files.iter().map(|f| f.num_commits()).sum()
}
}
/// Access fundamentals
impl Graph {
fn lookup_by_id(&self, id: &gix_hash::oid) -> Option<LookupByIdResult<'_>> {
let mut current_file_start = 0;
for file in &self.files {
if let Some(lex_pos) = file.lookup(id) {
return Some(LookupByIdResult {
file,
file_pos: lex_pos,
graph_pos: Position(current_file_start + lex_pos.0),
});
}
current_file_start += file.num_commits();
}
None
}
fn lookup_by_pos(&self, pos: Position) -> LookupByPositionResult<'_> {
let mut remaining = pos.0;
for (file_index, file) in self.files.iter().enumerate() {
match remaining.checked_sub(file.num_commits()) {
Some(v) => remaining = v,
None => {
return LookupByPositionResult {
file,
_file_index: file_index,
pos: file::Position(remaining),
}
}
}
}
panic!("graph position too large: {}", pos.0);
}
}
#[derive(Clone)]
struct LookupByIdResult<'a> {
pub file: &'a File,
pub graph_pos: Position,
pub file_pos: file::Position,
}
#[derive(Clone)]
struct LookupByPositionResult<'a> {
pub file: &'a File,
pub _file_index: usize,
pub pos: file::Position,
}
|