Skip to content

Commit 7cee17e

Browse files
committed
refactor (#16)
1 parent 9ba7921 commit 7cee17e

File tree

2 files changed

+123
-116
lines changed

2 files changed

+123
-116
lines changed

src/index/diff.rs

Lines changed: 3 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use crate::{Change, CrateVersion, Index};
22
use git_repository as git;
3-
use git_repository::bstr::BStr;
4-
use git_repository::diff::tree::visit::Action;
53
use git_repository::prelude::{FindExt, ObjectIdExt, TreeIterExt};
64
use git_repository::refs::transaction::PreviousValue;
7-
use similar::ChangeTag;
85
use std::convert::TryFrom;
96

107
static LINE_ADDED_INDICATOR: char = '+';
118

9+
mod delegate;
10+
use delegate::Delegate;
11+
1212
/// The error returned by methods dealing with obtaining index changes.
1313
#[derive(Debug, thiserror::Error)]
1414
#[allow(missing_docs)]
@@ -175,119 +175,6 @@ impl Index {
175175
};
176176
let from = into_tree(from.into())?;
177177
let to = into_tree(to.into())?;
178-
struct Delegate<'repo> {
179-
changes: Vec<Change>,
180-
deletes: Vec<CrateVersion>,
181-
file_name: git::bstr::BString,
182-
err: Option<Error>,
183-
repo: &'repo git::Repository,
184-
}
185-
impl<'repo> Delegate<'repo> {
186-
fn from_repo(repo: &'repo git::Repository) -> Self {
187-
Delegate {
188-
changes: Vec::new(),
189-
deletes: Vec::new(),
190-
err: None,
191-
file_name: Default::default(),
192-
repo,
193-
}
194-
}
195-
fn handle(&mut self, change: git::diff::tree::visit::Change) -> Result<(), Error> {
196-
use git::diff::tree::visit::Change::*;
197-
use git::objs::tree::EntryMode::*;
198-
fn entry_data(
199-
repo: &git::Repository,
200-
entry: git::objs::tree::EntryMode,
201-
oid: git::hash::ObjectId,
202-
) -> Result<Option<git::Object<'_>>, Error> {
203-
matches!(entry, Blob | BlobExecutable)
204-
.then(|| repo.find_object(oid))
205-
.transpose()
206-
.map_err(Into::into)
207-
}
208-
use git::bstr::ByteSlice;
209-
match change {
210-
Addition { entry_mode, oid } => {
211-
if let Some(obj) = entry_data(self.repo, entry_mode, oid)? {
212-
for line in (&obj.data).lines() {
213-
self.changes
214-
.push(Change::Added(serde_json::from_slice(line)?));
215-
}
216-
}
217-
}
218-
Deletion { .. } => {
219-
self.changes.push(Change::Deleted {
220-
name: self.file_name.to_string(),
221-
});
222-
}
223-
Modification {
224-
previous_entry_mode,
225-
previous_oid,
226-
entry_mode,
227-
oid,
228-
} => {
229-
let pair = entry_data(self.repo, previous_entry_mode, previous_oid)?
230-
.zip(entry_data(self.repo, entry_mode, oid)?);
231-
if let Some((old, new)) = pair {
232-
let diff = similar::TextDiffConfig::default()
233-
.algorithm(similar::Algorithm::Myers)
234-
.diff_lines(old.data.as_slice(), new.data.as_slice());
235-
for change in diff.iter_all_changes() {
236-
match change.tag() {
237-
ChangeTag::Delete | ChangeTag::Insert => {
238-
let version =
239-
serde_json::from_slice::<CrateVersion>(change.value())?;
240-
if change.tag() == ChangeTag::Insert {
241-
self.changes.push(if version.yanked {
242-
Change::Yanked(version)
243-
} else {
244-
Change::Added(version)
245-
});
246-
} else {
247-
self.deletes.push(version);
248-
}
249-
}
250-
ChangeTag::Equal => {}
251-
}
252-
}
253-
}
254-
}
255-
}
256-
Ok(())
257-
}
258-
fn into_result(self) -> Result<Vec<Change>, Error> {
259-
// assert_eq!(
260-
// self.deletes.len(),
261-
// 0,
262-
// "TODO: handle apparent version deletions"
263-
// );
264-
match self.err {
265-
Some(err) => Err(err),
266-
None => Ok(self.changes),
267-
}
268-
}
269-
}
270-
impl git::diff::tree::Visit for Delegate<'_> {
271-
fn pop_front_tracked_path_and_set_current(&mut self) {}
272-
fn push_back_tracked_path_component(&mut self, _component: &BStr) {}
273-
fn push_path_component(&mut self, component: &BStr) {
274-
use git::bstr::ByteVec;
275-
self.file_name.clear();
276-
self.file_name.push_str(component);
277-
}
278-
fn pop_path_component(&mut self) {}
279-
280-
fn visit(&mut self, change: git::diff::tree::visit::Change) -> Action {
281-
match self.handle(change) {
282-
Ok(()) => Action::Continue,
283-
Err(err) => {
284-
self.err = err.into();
285-
Action::Cancel
286-
}
287-
}
288-
}
289-
}
290-
291178
let mut delegate = Delegate::from_repo(&self.repo);
292179
let file_changes = git::objs::TreeRefIter::from_bytes(&from.data).changes_needed(
293180
git::objs::TreeRefIter::from_bytes(&to.data),

src/index/diff/delegate.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
use crate::index::diff::Error;
2+
use crate::{Change, CrateVersion};
3+
use git_repository as git;
4+
use git_repository::diff::tree::visit::Action;
5+
use similar::ChangeTag;
6+
7+
pub(crate) struct Delegate<'repo> {
8+
changes: Vec<Change>,
9+
deletes: Vec<CrateVersion>,
10+
file_name: git::bstr::BString,
11+
err: Option<Error>,
12+
repo: &'repo git::Repository,
13+
}
14+
15+
impl<'repo> Delegate<'repo> {
16+
pub fn from_repo(repo: &'repo git::Repository) -> Self {
17+
Delegate {
18+
changes: Vec::new(),
19+
deletes: Vec::new(),
20+
err: None,
21+
file_name: Default::default(),
22+
repo,
23+
}
24+
}
25+
fn handle(&mut self, change: git::diff::tree::visit::Change) -> Result<(), Error> {
26+
use git::diff::tree::visit::Change::*;
27+
use git::objs::tree::EntryMode::*;
28+
fn entry_data(
29+
repo: &git::Repository,
30+
entry: git::objs::tree::EntryMode,
31+
oid: git::hash::ObjectId,
32+
) -> Result<Option<git::Object<'_>>, Error> {
33+
matches!(entry, Blob | BlobExecutable)
34+
.then(|| repo.find_object(oid))
35+
.transpose()
36+
.map_err(Into::into)
37+
}
38+
use git::bstr::ByteSlice;
39+
match change {
40+
Addition { entry_mode, oid } => {
41+
if let Some(obj) = entry_data(self.repo, entry_mode, oid)? {
42+
for line in (&obj.data).lines() {
43+
self.changes
44+
.push(Change::Added(serde_json::from_slice(line)?));
45+
}
46+
}
47+
}
48+
Deletion { .. } => {
49+
self.changes.push(Change::Deleted {
50+
name: self.file_name.to_string(),
51+
});
52+
}
53+
Modification {
54+
previous_entry_mode,
55+
previous_oid,
56+
entry_mode,
57+
oid,
58+
} => {
59+
let pair = entry_data(self.repo, previous_entry_mode, previous_oid)?
60+
.zip(entry_data(self.repo, entry_mode, oid)?);
61+
if let Some((old, new)) = pair {
62+
let diff = similar::TextDiffConfig::default()
63+
.algorithm(similar::Algorithm::Myers)
64+
.diff_lines(old.data.as_slice(), new.data.as_slice());
65+
for change in diff.iter_all_changes() {
66+
match change.tag() {
67+
ChangeTag::Delete | ChangeTag::Insert => {
68+
let version =
69+
serde_json::from_slice::<CrateVersion>(change.value())?;
70+
if change.tag() == ChangeTag::Insert {
71+
self.changes.push(if version.yanked {
72+
Change::Yanked(version)
73+
} else {
74+
Change::Added(version)
75+
});
76+
} else {
77+
self.deletes.push(version);
78+
}
79+
}
80+
ChangeTag::Equal => {}
81+
}
82+
}
83+
}
84+
}
85+
}
86+
Ok(())
87+
}
88+
pub fn into_result(self) -> Result<Vec<Change>, Error> {
89+
// assert_eq!(
90+
// self.deletes.len(),
91+
// 0,
92+
// "TODO: handle apparent version deletions"
93+
// );
94+
match self.err {
95+
Some(err) => Err(err),
96+
None => Ok(self.changes),
97+
}
98+
}
99+
}
100+
101+
impl git::diff::tree::Visit for Delegate<'_> {
102+
fn pop_front_tracked_path_and_set_current(&mut self) {}
103+
fn push_back_tracked_path_component(&mut self, _component: &git::bstr::BStr) {}
104+
fn push_path_component(&mut self, component: &git::bstr::BStr) {
105+
use git::bstr::ByteVec;
106+
self.file_name.clear();
107+
self.file_name.push_str(component);
108+
}
109+
fn pop_path_component(&mut self) {}
110+
111+
fn visit(&mut self, change: git::diff::tree::visit::Change) -> Action {
112+
match self.handle(change) {
113+
Ok(()) => Action::Continue,
114+
Err(err) => {
115+
self.err = err.into();
116+
Action::Cancel
117+
}
118+
}
119+
}
120+
}

0 commit comments

Comments
 (0)