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
use git_object::tree::EntryMode;
use crate::{bstr::ByteSlice, Id, Repository};
#[derive(Debug, Clone, Copy)]
pub enum Event<'old, 'new> {
Addition {
entry_mode: git_object::tree::EntryMode,
id: Id<'new>,
},
Deletion {
entry_mode: git_object::tree::EntryMode,
id: Id<'old>,
},
Modification {
previous_entry_mode: git_object::tree::EntryMode,
previous_id: Id<'old>,
entry_mode: git_object::tree::EntryMode,
id: Id<'new>,
},
}
pub struct DiffPlatform<'old, 'new> {
old: crate::Object<'old>,
new: crate::Object<'new>,
algo: git_diff::text::Algorithm,
}
impl<'old, 'new> Event<'old, 'new> {
fn repo(&self) -> &Repository {
match self {
Event::Addition { id, .. } => id.repo,
Event::Deletion { id, .. } => id.repo,
Event::Modification { id, .. } => id.repo,
}
}
}
pub mod event {
pub mod diff {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error("Could not find the previous object to diff against")]
FindPrevious(#[from] crate::object::find::existing::Error),
#[error("Could not obtain diff algorithm from configuration")]
DiffAlgorithm(#[from] crate::config::diff::algorithm::Error),
}
}
}
impl<'old, 'new> Event<'old, 'new> {
pub fn diff(&self) -> Option<Result<DiffPlatform<'old, 'new>, event::diff::Error>> {
match self {
Event::Modification {
previous_entry_mode: EntryMode::BlobExecutable | EntryMode::Blob,
previous_id,
entry_mode: EntryMode::BlobExecutable | EntryMode::Blob,
id,
} => match previous_id.object().and_then(|old| id.object().map(|new| (old, new))) {
Ok((old, new)) => {
let algo = match self.repo().config.diff_algorithm() {
Ok(algo) => algo,
Err(err) => return Some(Err(err.into())),
};
Some(Ok(DiffPlatform { old, new, algo }))
}
Err(err) => Some(Err(err.into())),
},
_ => None,
}
}
}
impl<'old, 'new> DiffPlatform<'old, 'new> {
pub fn lines<FnS, S>(&self, new_sink: FnS) -> S::Out
where
FnS: for<'a> FnOnce(&git_diff::text::imara::intern::InternedInput<&'a [u8]>) -> S,
S: git_diff::text::imara::Sink,
{
git_diff::text::with(
self.old.data.as_bstr(),
self.new.data.as_bstr(),
self.algo,
git_diff::text::imara::intern::InternedInput::new,
new_sink,
)
.1
}
}