-
-
Notifications
You must be signed in to change notification settings - Fork 340
/
Copy pathdiff.rs
113 lines (104 loc) · 3.75 KB
/
diff.rs
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
use gix::bstr::{BString, ByteSlice};
use gix::objs::tree::EntryMode;
use gix::odb::store::RefreshMode;
use gix::prelude::ObjectIdExt;
pub fn tree(
mut repo: gix::Repository,
out: &mut dyn std::io::Write,
old_treeish: BString,
new_treeish: BString,
) -> anyhow::Result<()> {
repo.object_cache_size_if_unset(repo.compute_object_cache_size_for_tree_diffs(&**repo.index_or_empty()?));
repo.objects.refresh = RefreshMode::Never;
let old_tree_id = repo.rev_parse_single(old_treeish.as_bstr())?;
let new_tree_id = repo.rev_parse_single(new_treeish.as_bstr())?;
let old_tree = old_tree_id.object()?.peel_to_tree()?;
let new_tree = new_tree_id.object()?.peel_to_tree()?;
let changes = repo.diff_tree_to_tree(&old_tree, &new_tree, None)?;
writeln!(
out,
"Diffing trees `{old_treeish}` ({old_tree_id}) -> `{new_treeish}` ({new_tree_id})\n"
)?;
write_changes(&repo, out, changes)?;
Ok(())
}
fn write_changes(
repo: &gix::Repository,
mut out: impl std::io::Write,
changes: Vec<gix::diff::tree_with_rewrites::Change>,
) -> Result<(), std::io::Error> {
for change in changes {
match change {
gix::diff::tree_with_rewrites::Change::Addition {
location,
id,
entry_mode,
..
} => {
writeln!(out, "A: {}", typed_location(location, entry_mode))?;
writeln!(out, " {}", id.attach(repo).shorten_or_id())?;
writeln!(out, " -> {:o}", entry_mode.0)?;
}
gix::diff::tree_with_rewrites::Change::Deletion {
location,
id,
entry_mode,
..
} => {
writeln!(out, "D: {}", typed_location(location, entry_mode))?;
writeln!(out, " {}", id.attach(repo).shorten_or_id())?;
writeln!(out, " {:o} ->", entry_mode.0)?;
}
gix::diff::tree_with_rewrites::Change::Modification {
location,
previous_id,
id,
previous_entry_mode,
entry_mode,
} => {
writeln!(out, "M: {}", typed_location(location, entry_mode))?;
writeln!(
out,
" {previous_id} -> {id}",
previous_id = previous_id.attach(repo).shorten_or_id(),
id = id.attach(repo).shorten_or_id()
)?;
if previous_entry_mode != entry_mode {
writeln!(out, " {:o} -> {:o}", previous_entry_mode.0, entry_mode.0)?;
}
}
gix::diff::tree_with_rewrites::Change::Rewrite {
source_location,
source_id,
id,
location,
source_entry_mode,
entry_mode,
..
} => {
writeln!(
out,
"R: {source} -> {dest}",
source = typed_location(source_location, source_entry_mode),
dest = typed_location(location, entry_mode)
)?;
writeln!(
out,
" {source_id} -> {id}",
source_id = source_id.attach(repo).shorten_or_id(),
id = id.attach(repo).shorten_or_id()
)?;
if source_entry_mode != entry_mode {
writeln!(out, " {:o} -> {:o}", source_entry_mode.0, entry_mode.0)?;
}
}
};
}
Ok(())
}
fn typed_location(mut location: BString, mode: EntryMode) -> BString {
if mode.is_tree() {
location.push(b'/');
}
location
}