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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//! Repository-scoped tree and index diffs via [`Diff`].
use crate::config::ConfigSet;
use crate::diff::targets::{
collect_diff_entries_for_patch_target, collect_files_for_target,
collect_tree_structured_for_target, file_diffs_from_entries,
};
use crate::diff::TreeDiffStructured;
use crate::diff::{
build_file_diffs, diff_index_to_tree, diff_index_to_worktree, diff_trees, DiffDetail,
DiffEntry, DiffFilesOutput, DiffOptions,
};
use crate::diff::{DiffTarget, FileDiff};
use crate::error::Result;
use crate::index::Index;
use crate::objects::ObjectId;
use crate::parallel::ThreadPolicy;
use crate::repo::Repository;
/// Compare trees, the index, and the working tree for one repository.
#[derive(Debug, Copy, Clone)]
pub struct Diff<'repo> {
repo: &'repo Repository,
}
impl<'repo> Diff<'repo> {
/// Bind diff helpers to `repo`.
#[inline]
#[must_use]
pub fn new(repo: &'repo Repository) -> Self {
Self { repo }
}
/// Underlying repository.
#[inline]
#[must_use]
pub fn repository(&self) -> &'repo Repository {
self.repo
}
/// Diff two tree oids (either side may be `None` for an empty tree).
///
/// # Errors
///
/// Propagates ODB read and tree walk errors.
///
/// # Examples
///
/// See the library guide on [diffing](https://grit-scm.com/docs/library/diff/).
#[inline]
pub fn tree_to_tree(
&self,
old_tree: Option<&ObjectId>,
new_tree: Option<&ObjectId>,
) -> Result<Vec<DiffEntry>> {
diff_trees(self.repo.odb(), old_tree, new_tree, "")
}
/// Diff the index against a tree (typically `HEAD`'s tree).
///
/// # Errors
///
/// Propagates ODB and index diff errors.
#[inline]
pub fn index_to_tree(
&self,
index: &Index,
tree_oid: Option<&ObjectId>,
ignore_submodules: bool,
) -> Result<Vec<DiffEntry>> {
diff_index_to_tree(self.repo.odb(), index, tree_oid, ignore_submodules)
}
/// Diff the working tree against the index.
///
/// # Errors
///
/// Returns an error when the repository has no work tree or diff I/O fails.
#[inline]
pub fn worktree_to_index(
&self,
index: &mut Index,
ignore_submodule_untracked: bool,
simplify_gitlinks: bool,
) -> Result<Vec<DiffEntry>> {
let work_tree = self
.repo
.work_tree()
.ok_or_else(|| crate::error::Error::NotARepository("bare repository".into()))?;
diff_index_to_worktree(
self.repo.odb(),
index,
work_tree,
ignore_submodule_untracked,
simplify_gitlinks,
)
}
/// Structured per-file diffs for `target`, honoring `pathspecs` and line-diff `opts`.
///
/// # Errors
///
/// Propagates index, ODB, and worktree diff failures.
pub fn files(
&self,
target: &DiffTarget,
pathspecs: &[String],
opts: &DiffOptions,
) -> Result<Vec<FileDiff>> {
collect_files_for_target(self.repo, target, pathspecs, opts.clone())
}
/// Build per-file diff output for tree or index diff entries (stat, name-only, patch).
///
/// # Errors
///
/// Propagates object database and diff errors from [`build_file_diffs`].
pub fn files_with_detail(
&self,
entries: Vec<DiffEntry>,
detail: DiffDetail,
diff_options: DiffOptions,
config: &ConfigSet,
thread_policy: &ThreadPolicy,
) -> Result<DiffFilesOutput> {
build_file_diffs(
self.repo.odb(),
entries,
detail,
diff_options,
config,
thread_policy,
)
}
/// Build [`FileDiff`] rows from an existing tree diff entry list (e.g. stash W vs index).
///
/// # Errors
///
/// Propagates object read and structured diff errors.
pub fn files_from_entries(
&self,
entries: Vec<DiffEntry>,
opts: &DiffOptions,
) -> Result<Vec<FileDiff>> {
file_diffs_from_entries(self.repo, entries, opts.clone())
}
/// Structured diff rows for [`write_patch_structured`](super::write_patch_structured) (patch-text output).
///
/// # Errors
///
/// Propagates index, ODB, and worktree diff failures.
pub fn tree_structured(
&self,
target: &DiffTarget,
pathspecs: &[String],
opts: &DiffOptions,
) -> Result<Vec<TreeDiffStructured>> {
collect_tree_structured_for_target(self.repo, target, pathspecs, opts.clone())
}
/// Tree diff entries for commit-range [`write_patch`](super::write_patch) (skips structured line diffs).
///
/// # Errors
///
/// Propagates diff failures; returns an error for worktree/index patch targets.
pub fn patch_entries(
&self,
target: &DiffTarget,
pathspecs: &[String],
opts: &DiffOptions,
) -> Result<Vec<DiffEntry>> {
collect_diff_entries_for_patch_target(self.repo, target, pathspecs, opts.clone())
}
}