gitoxide_core/repository/
diff.rs

1use gix::bstr::{BString, ByteSlice};
2use gix::objs::tree::EntryMode;
3use gix::odb::store::RefreshMode;
4use gix::prelude::ObjectIdExt;
5
6pub fn tree(
7    mut repo: gix::Repository,
8    out: &mut dyn std::io::Write,
9    old_treeish: BString,
10    new_treeish: BString,
11) -> anyhow::Result<()> {
12    repo.object_cache_size_if_unset(repo.compute_object_cache_size_for_tree_diffs(&**repo.index_or_empty()?));
13    repo.objects.refresh = RefreshMode::Never;
14
15    let old_tree_id = repo.rev_parse_single(old_treeish.as_bstr())?;
16    let new_tree_id = repo.rev_parse_single(new_treeish.as_bstr())?;
17
18    let old_tree = old_tree_id.object()?.peel_to_tree()?;
19    let new_tree = new_tree_id.object()?.peel_to_tree()?;
20
21    let changes = repo.diff_tree_to_tree(&old_tree, &new_tree, None)?;
22
23    writeln!(
24        out,
25        "Diffing trees `{old_treeish}` ({old_tree_id}) -> `{new_treeish}` ({new_tree_id})\n"
26    )?;
27    write_changes(&repo, out, changes)?;
28
29    Ok(())
30}
31
32fn write_changes(
33    repo: &gix::Repository,
34    mut out: impl std::io::Write,
35    changes: Vec<gix::diff::tree_with_rewrites::Change>,
36) -> Result<(), std::io::Error> {
37    for change in changes {
38        match change {
39            gix::diff::tree_with_rewrites::Change::Addition {
40                location,
41                id,
42                entry_mode,
43                ..
44            } => {
45                writeln!(out, "A: {}", typed_location(location, entry_mode))?;
46                writeln!(out, "  {}", id.attach(repo).shorten_or_id())?;
47                writeln!(out, "  -> {:o}", entry_mode.0)?;
48            }
49            gix::diff::tree_with_rewrites::Change::Deletion {
50                location,
51                id,
52                entry_mode,
53                ..
54            } => {
55                writeln!(out, "D: {}", typed_location(location, entry_mode))?;
56                writeln!(out, "  {}", id.attach(repo).shorten_or_id())?;
57                writeln!(out, "  {:o} ->", entry_mode.0)?;
58            }
59            gix::diff::tree_with_rewrites::Change::Modification {
60                location,
61                previous_id,
62                id,
63                previous_entry_mode,
64                entry_mode,
65            } => {
66                writeln!(out, "M: {}", typed_location(location, entry_mode))?;
67                writeln!(
68                    out,
69                    "  {previous_id} -> {id}",
70                    previous_id = previous_id.attach(repo).shorten_or_id(),
71                    id = id.attach(repo).shorten_or_id()
72                )?;
73                if previous_entry_mode != entry_mode {
74                    writeln!(out, "  {:o} -> {:o}", previous_entry_mode.0, entry_mode.0)?;
75                }
76            }
77            gix::diff::tree_with_rewrites::Change::Rewrite {
78                source_location,
79                source_id,
80                id,
81                location,
82                source_entry_mode,
83                entry_mode,
84                ..
85            } => {
86                writeln!(
87                    out,
88                    "R: {source} -> {dest}",
89                    source = typed_location(source_location, source_entry_mode),
90                    dest = typed_location(location, entry_mode)
91                )?;
92                writeln!(
93                    out,
94                    "  {source_id} -> {id}",
95                    source_id = source_id.attach(repo).shorten_or_id(),
96                    id = id.attach(repo).shorten_or_id()
97                )?;
98                if source_entry_mode != entry_mode {
99                    writeln!(out, "  {:o} -> {:o}", source_entry_mode.0, entry_mode.0)?;
100                }
101            }
102        };
103    }
104
105    Ok(())
106}
107
108fn typed_location(mut location: BString, mode: EntryMode) -> BString {
109    if mode.is_tree() {
110        location.push(b'/');
111    }
112    location
113}