Skip to content

Commit 9159397

Browse files
committed
feat: upgrade to git-repository v0.24 to simplify diff implementation.
1 parent cd23a28 commit 9159397

File tree

3 files changed

+33
-72
lines changed

3 files changed

+33
-72
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ include = ["src/**/*", "LICENSE.md", "README.md", "CHANGELOG.md"]
1515
test = false
1616

1717
[dependencies]
18-
git-repository = { version = "0.23.1", default-features = false, features = ["max-performance-safe"] }
18+
git-repository = { version = "0.24.0", default-features = false, features = ["max-performance-safe"] }
1919
similar = { version = "2.2.0", features = ["bytes"] }
2020
serde = { version = "1", features = ["std", "derive"] }
2121
serde_json = "1"
22-
bstr = "0.2.17"
22+
bstr = "1.0.1"
2323
thiserror = "1.0.32"
2424

2525
[dependencies.git2]

src/index/diff/delegate.rs

Lines changed: 25 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,41 @@ use crate::index::diff::Error;
22
use crate::{Change, CrateVersion};
33
use bstr::BStr;
44
use git_repository as git;
5-
use git_repository::diff::tree::visit::Action;
65
use similar::ChangeTag;
76
use std::collections::BTreeSet;
87

9-
pub(crate) struct Delegate<'repo> {
8+
#[derive(Default)]
9+
pub(crate) struct Delegate {
1010
changes: Vec<Change>,
1111
delete_version_ids: BTreeSet<u64>,
12-
file_name: git::bstr::BString,
1312
err: Option<Error>,
14-
repo: &'repo git::Repository,
1513
}
1614

17-
impl<'repo> Delegate<'repo> {
18-
pub fn from_repo(repo: &'repo git::Repository) -> Self {
19-
Delegate {
20-
changes: Vec::new(),
21-
delete_version_ids: BTreeSet::new(),
22-
err: None,
23-
file_name: Default::default(),
24-
repo,
25-
}
26-
}
27-
fn handle(&mut self, change: git::diff::tree::visit::Change) -> Result<(), Error> {
15+
impl Delegate {
16+
pub fn handle(
17+
&mut self,
18+
change: git::object::tree::diff::Change<'_, '_, '_>,
19+
) -> Result<git::object::tree::diff::Action, Error> {
2820
use git::bstr::ByteSlice;
29-
use git::diff::tree::visit::Change::*;
21+
use git::object::tree::diff::change::Event::*;
3022
use git::objs::tree::EntryMode::*;
3123
fn entry_data(
32-
repo: &git::Repository,
3324
entry: git::objs::tree::EntryMode,
34-
oid: git::hash::ObjectId,
25+
id: git::Id<'_>,
3526
) -> Result<Option<git::Object<'_>>, Error> {
3627
matches!(entry, Blob | BlobExecutable)
37-
.then(|| repo.find_object(oid))
28+
.then(|| id.object())
3829
.transpose()
3930
.map_err(Into::into)
4031
}
41-
if self.file_name.contains(&b'.') {
42-
return Ok(());
32+
if change.location.contains(&b'.') {
33+
return Ok(Default::default());
4334
}
44-
match change {
45-
Addition { entry_mode, oid } => {
46-
if let Some(obj) = entry_data(self.repo, entry_mode, oid)? {
35+
match change.event {
36+
Addition { entry_mode, id } => {
37+
if let Some(obj) = entry_data(entry_mode, id)? {
4738
for line in (&obj.data).lines() {
48-
let version = version_from_json_line(line, self.file_name.as_ref())?;
39+
let version = version_from_json_line(line, change.location)?;
4940
self.changes.push(if version.yanked {
5041
Change::Yanked(version)
5142
} else {
@@ -57,29 +48,27 @@ impl<'repo> Delegate<'repo> {
5748
Deletion { entry_mode, .. } => {
5849
if entry_mode.is_no_tree() {
5950
self.changes.push(Change::Deleted {
60-
name: self.file_name.to_string(),
51+
name: change.location.to_string(),
6152
});
6253
}
6354
}
6455
Modification {
6556
previous_entry_mode,
66-
previous_oid,
57+
previous_id,
6758
entry_mode,
68-
oid,
59+
id,
6960
} => {
70-
let pair = entry_data(self.repo, previous_entry_mode, previous_oid)?
71-
.zip(entry_data(self.repo, entry_mode, oid)?);
61+
let pair =
62+
entry_data(previous_entry_mode, previous_id)?.zip(entry_data(entry_mode, id)?);
7263
if let Some((old, new)) = pair {
7364
let diff = similar::TextDiffConfig::default()
7465
.algorithm(similar::Algorithm::Myers)
7566
.diff_lines(old.data.as_slice(), new.data.as_slice());
67+
let location = change.location;
7668
for change in diff.iter_all_changes() {
7769
match change.tag() {
7870
ChangeTag::Delete | ChangeTag::Insert => {
79-
let version = version_from_json_line(
80-
change.value(),
81-
self.file_name.as_ref(),
82-
)?;
71+
let version = version_from_json_line(change.value(), location)?;
8372
if change.tag() == ChangeTag::Insert {
8473
self.changes.push(if version.yanked {
8574
Change::Yanked(version)
@@ -96,8 +85,9 @@ impl<'repo> Delegate<'repo> {
9685
}
9786
}
9887
}
99-
Ok(())
88+
Ok(Default::default())
10089
}
90+
10191
pub fn into_result(mut self) -> Result<Vec<Change>, Error> {
10292
match self.err {
10393
Some(err) => Err(err),
@@ -117,27 +107,6 @@ impl<'repo> Delegate<'repo> {
117107
}
118108
}
119109

120-
impl git::diff::tree::Visit for Delegate<'_> {
121-
fn pop_front_tracked_path_and_set_current(&mut self) {}
122-
fn push_back_tracked_path_component(&mut self, _component: &git::bstr::BStr) {}
123-
fn push_path_component(&mut self, component: &git::bstr::BStr) {
124-
use git::bstr::ByteVec;
125-
self.file_name.clear();
126-
self.file_name.push_str(component);
127-
}
128-
fn pop_path_component(&mut self) {}
129-
130-
fn visit(&mut self, change: git::diff::tree::visit::Change) -> Action {
131-
match self.handle(change) {
132-
Ok(()) => Action::Continue,
133-
Err(err) => {
134-
self.err = err.into();
135-
Action::Cancel
136-
}
137-
}
138-
}
139-
}
140-
141110
fn version_from_json_line(line: &[u8], file_name: &BStr) -> Result<CrateVersion, Error> {
142111
serde_json::from_slice(line).map_err(|err| Error::VersionDecode {
143112
source: err,

src/index/diff/mod.rs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{Change, Index};
22
use git_repository as git;
3-
use git_repository::prelude::{FindExt, ObjectIdExt};
3+
use git_repository::prelude::ObjectIdExt;
44
use git_repository::refs::transaction::PreviousValue;
55
use std::convert::TryFrom;
66

@@ -22,7 +22,7 @@ pub enum Error {
2222
#[error("Couldn't get the tree of a commit for diffing purposes")]
2323
PeelToTree(#[from] git::object::peel::to_kind::Error),
2424
#[error("Failed to diff two trees to find changed crates")]
25-
Diff(#[from] git::diff::tree::changes::Error),
25+
Diff(#[from] git::object::tree::diff::Error),
2626
#[error("Failed to decode {line:?} in file {file_name:?} as crate version")]
2727
VersionDecode {
2828
source: serde_json::Error,
@@ -105,18 +105,10 @@ impl Index {
105105
};
106106
let from = into_tree(from.into())?;
107107
let to = into_tree(to.into())?;
108-
let mut delegate = Delegate::from_repo(&self.repo);
109-
let res = git::diff::tree::Changes::from(git::objs::TreeRefIter::from_bytes(&from.data))
110-
.needed_to_obtain(
111-
git::objs::TreeRefIter::from_bytes(&to.data),
112-
git::diff::tree::State::default(),
113-
|id, buf| self.repo.objects.find_tree_iter(id, buf),
114-
&mut delegate,
115-
);
116-
match res.err() {
117-
None | Some(git::diff::tree::changes::Error::Cancelled) => { /*error in delegate*/ }
118-
Some(err) => return Err(err.into()),
119-
}
108+
let mut delegate = Delegate::default();
109+
from.changes()
110+
.track_filename()
111+
.for_each_to_obtain_tree(&to, |change| delegate.handle(change))?;
120112
delegate.into_result()
121113
}
122114
}

0 commit comments

Comments
 (0)