1use crate::diff::targets::collect_files_for_target;
3use crate::diff::{
4 diff_index_to_tree, diff_index_to_worktree, diff_trees, diff_trees_with_renames_and_policy,
5 DiffEntry, DiffOptions,
6};
7use crate::diff::{DiffTarget, FileDiff, UncommittedDiff};
8use crate::error::Result;
9use crate::index::Index;
10use crate::objects::ObjectId;
11use crate::repo::Repository;
12
13#[derive(Debug, Copy, Clone)]
15pub struct Diff<'repo> {
16 repo: &'repo Repository,
17}
18
19impl<'repo> Diff<'repo> {
20 #[inline]
22 #[must_use]
23 pub fn new(repo: &'repo Repository) -> Self {
24 Self { repo }
25 }
26
27 #[inline]
29 #[must_use]
30 pub fn repository(&self) -> &'repo Repository {
31 self.repo
32 }
33
34 #[inline]
48 pub fn tree_to_tree(
49 &self,
50 old_tree: Option<&ObjectId>,
51 new_tree: Option<&ObjectId>,
52 ) -> Result<Vec<DiffEntry>> {
53 diff_trees(self.repo.odb(), old_tree, new_tree, "")
54 }
55
56 pub fn tree_to_tree_renames(
62 &self,
63 old_tree: Option<&ObjectId>,
64 new_tree: Option<&ObjectId>,
65 options: &DiffOptions,
66 ) -> Result<Vec<DiffEntry>> {
67 let config = self.repo.config()?;
68 diff_trees_with_renames_and_policy(
69 self.repo.odb(),
70 old_tree,
71 new_tree,
72 "",
73 options.rename_threshold_u32(),
74 config.as_ref(),
75 &self.repo.thread_policy(),
76 )
77 }
78
79 #[inline]
85 pub fn index_to_tree(
86 &self,
87 index: &Index,
88 tree_oid: Option<&ObjectId>,
89 ignore_submodules: bool,
90 ) -> Result<Vec<DiffEntry>> {
91 diff_index_to_tree(self.repo.odb(), index, tree_oid, ignore_submodules)
92 }
93
94 #[inline]
100 pub fn worktree_to_index(
101 &self,
102 index: &mut Index,
103 ignore_submodule_untracked: bool,
104 simplify_gitlinks: bool,
105 ) -> Result<Vec<DiffEntry>> {
106 let work_tree = self
107 .repo
108 .work_tree()
109 .ok_or(crate::error::Error::RequiresWorkTree)?;
110 diff_index_to_worktree(
111 self.repo.odb(),
112 index,
113 work_tree,
114 ignore_submodule_untracked,
115 simplify_gitlinks,
116 )
117 }
118
119 pub fn uncommitted(&self) -> Result<UncommittedDiff<'repo>> {
125 let index = self.repo.index_handle().load_preserving_sparse()?;
126 Ok(UncommittedDiff::new(self.repo, index))
127 }
128
129 pub fn files(
135 &self,
136 target: &DiffTarget,
137 pathspecs: &[String],
138 opts: &DiffOptions,
139 ) -> Result<Vec<FileDiff>> {
140 collect_files_for_target(self.repo, target, pathspecs, opts.clone())
141 }
142}