Skip to content

Commit e51f3cd

Browse files
committed
break through API surface and sketch delegate calling user-provided function (#470)
1 parent c857b9b commit e51f3cd

File tree

1 file changed

+109
-5
lines changed
  • git-repository/src/object/tree

1 file changed

+109
-5
lines changed

git-repository/src/object/tree/mod.rs

+109-5
Original file line numberDiff line numberDiff line change
@@ -65,22 +65,126 @@ impl<'repo> Tree<'repo> {
6565
#[allow(missing_docs)]
6666
///
6767
pub mod diff {
68-
use crate::Tree;
68+
use crate::bstr::BStr;
69+
use crate::ext::ObjectIdExt;
70+
use crate::{Id, Repository, Tree};
71+
use git_object::TreeRefIter;
72+
use git_odb::FindExt;
6973

74+
/// Represents any possible change in order to turn one tree into another.
75+
#[derive(Debug, Clone, Copy)]
76+
pub enum Event<'repo, 'other_repo> {
77+
/// An entry was added, like the addition of a file or directory.
78+
Addition {
79+
/// The mode of the added entry.
80+
entry_mode: git_object::tree::EntryMode,
81+
/// The object id of the added entry.
82+
id: Id<'other_repo>,
83+
},
84+
/// An entry was deleted, like the deletion of a file or directory.
85+
Deletion {
86+
/// The mode of the deleted entry.
87+
entry_mode: git_object::tree::EntryMode,
88+
/// The object id of the deleted entry.
89+
id: Id<'repo>,
90+
},
91+
/// An entry was modified, e.g. changing the contents of a file adjusts its object id and turning
92+
/// a file into a symbolic link adjusts its mode.
93+
Modification {
94+
/// The mode of the entry before the modification.
95+
previous_entry_mode: git_object::tree::EntryMode,
96+
/// The object id of the entry before the modification.
97+
previous_id: Id<'repo>,
98+
99+
/// The mode of the entry after the modification.
100+
entry_mode: git_object::tree::EntryMode,
101+
/// The object id after the modification.
102+
id: Id<'other_repo>,
103+
},
104+
}
105+
106+
/// Diffing
70107
impl<'repo> Tree<'repo> {
108+
/// Return a platform to see the changes needed to create other trees, for instance.
71109
pub fn changes<'other_repo, 'a>(&'a self) -> Platform<'a, 'repo> {
72-
Platform { lhs: self }
110+
Platform {
111+
state: Default::default(),
112+
lhs: self,
113+
}
73114
}
74115
}
75116

76-
#[allow(dead_code)]
77117
pub struct Platform<'a, 'repo> {
118+
state: git_diff::tree::State,
78119
lhs: &'a Tree<'repo>,
79120
}
80121

122+
/// Add the item to compare to.
81123
impl<'a, 'repo> Platform<'a, 'repo> {
82-
pub fn to_obtain_tree(&self, _other: &Tree<'_>) {
83-
todo!()
124+
pub fn to_obtain_tree<'other_repo>(
125+
&mut self,
126+
other: &Tree<'other_repo>,
127+
for_each: impl FnMut(Event<'repo, 'other_repo>) -> git_diff::tree::visit::Action,
128+
) -> Result<(), git_diff::tree::changes::Error> {
129+
let repo = self.lhs.repo;
130+
let mut delegate = Delegate {
131+
repo: self.lhs.repo,
132+
other_repo: other.repo,
133+
visit: for_each,
134+
};
135+
git_diff::tree::Changes::from(TreeRefIter::from_bytes(&self.lhs.data)).needed_to_obtain(
136+
TreeRefIter::from_bytes(&other.data),
137+
&mut self.state,
138+
|oid, buf| repo.objects.find_tree_iter(oid, buf),
139+
&mut delegate,
140+
)
141+
}
142+
}
143+
144+
struct Delegate<'repo, 'other_repo, VisitFn> {
145+
repo: &'repo Repository,
146+
other_repo: &'other_repo Repository,
147+
visit: VisitFn,
148+
}
149+
150+
impl<'repo, 'other_repo, VisitFn> git_diff::tree::Visit for Delegate<'repo, 'other_repo, VisitFn>
151+
where
152+
VisitFn: FnMut(Event<'repo, 'other_repo>) -> git_diff::tree::visit::Action,
153+
{
154+
fn pop_front_tracked_path_and_set_current(&mut self) {}
155+
156+
fn push_back_tracked_path_component(&mut self, _component: &BStr) {
157+
{}
158+
}
159+
160+
fn push_path_component(&mut self, _component: &BStr) {}
161+
162+
fn pop_path_component(&mut self) {}
163+
164+
fn visit(&mut self, change: git_diff::tree::visit::Change) -> git_diff::tree::visit::Action {
165+
use git_diff::tree::visit::Change::*;
166+
let event = match change {
167+
Addition { entry_mode, oid } => Event::Addition {
168+
entry_mode,
169+
id: oid.attach(self.other_repo),
170+
},
171+
Deletion { entry_mode, oid } => Event::Deletion {
172+
entry_mode,
173+
id: oid.attach(self.repo),
174+
},
175+
Modification {
176+
previous_entry_mode,
177+
previous_oid,
178+
entry_mode,
179+
oid,
180+
} => Event::Modification {
181+
previous_entry_mode,
182+
entry_mode,
183+
previous_id: previous_oid.attach(self.repo),
184+
id: oid.attach(self.other_repo),
185+
},
186+
};
187+
(self.visit)(event)
84188
}
85189
}
86190
}

0 commit comments

Comments
 (0)