Skip to content

Commit b28b7ca

Browse files
committed
Merge branch 'git-repository-upgrade'
2 parents acd06a1 + 377065e commit b28b7ca

File tree

4 files changed

+107
-33
lines changed

4 files changed

+107
-33
lines changed

Cargo.toml

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

1717
[dependencies]
18-
git-repository = { version = "0.25.0", default-features = false, features = ["max-performance-safe", "blocking-network-client", "blocking-http-transport"] }
19-
similar = { version = "2.2.0", features = ["bytes"] }
18+
git-repository = { version = "0.27.0", default-features = false, features = ["max-performance-safe", "blocking-network-client", "blocking-http-transport"] }
2019
serde = { version = "1", features = ["std", "derive"] }
2120
serde_json = "1"
2221
bstr = "1.0.1"

src/index/diff/delegate.rs

Lines changed: 80 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use crate::index::diff::Error;
22
use crate::{Change, CrateVersion};
33
use bstr::BStr;
44
use git_repository as git;
5-
use similar::ChangeTag;
65
use std::collections::BTreeSet;
6+
use std::ops::Range;
77

88
#[derive(Default)]
99
pub(crate) struct Delegate {
@@ -55,25 +55,87 @@ impl Delegate {
5555
Modification { .. } => {
5656
if let Some(diff) = change.event.diff().transpose()? {
5757
let location = change.location;
58-
for change in diff
59-
.text(git::diff::lines::Algorithm::Myers)
60-
.iter_all_changes()
61-
{
62-
match change.tag() {
63-
ChangeTag::Delete | ChangeTag::Insert => {
64-
let version = version_from_json_line(change.value(), location)?;
65-
if change.tag() == ChangeTag::Insert {
66-
self.changes.push(if version.yanked {
67-
Change::Yanked(version)
68-
} else {
69-
Change::Added(version)
70-
});
71-
} else {
72-
self.delete_version_ids.insert(version.id());
58+
59+
let input = diff.line_tokens();
60+
let mut err = None;
61+
git::diff::blob::diff(
62+
diff.algo,
63+
&input,
64+
|before: Range<u32>, after: Range<u32>| {
65+
if err.is_some() {
66+
return;
67+
}
68+
let mut lines_before = input.before
69+
[before.start as usize..before.end as usize]
70+
.iter()
71+
.map(|&line| input.interner[line].as_bstr())
72+
.peekable();
73+
let mut lines_after = input.after
74+
[after.start as usize..after.end as usize]
75+
.iter()
76+
.map(|&line| input.interner[line].as_bstr())
77+
.peekable();
78+
match (lines_before.peek().is_some(), lines_after.peek().is_some()) {
79+
(true, false) => {
80+
for removed in lines_before {
81+
match version_from_json_line(removed, location) {
82+
Ok(version) => {
83+
self.delete_version_ids.insert(version.id());
84+
}
85+
Err(e) => {
86+
err = Some(e);
87+
break;
88+
}
89+
}
90+
}
91+
}
92+
(false, true) => {
93+
for inserted in lines_after {
94+
match version_from_json_line(inserted, location) {
95+
Ok(version) => {
96+
self.changes.push(if version.yanked {
97+
Change::Yanked(version)
98+
} else {
99+
Change::Added(version)
100+
});
101+
}
102+
Err(e) => {
103+
err = Some(e);
104+
break;
105+
}
106+
}
107+
}
73108
}
109+
(true, true) => {
110+
for (removed, inserted) in lines_before.zip(lines_after) {
111+
match version_from_json_line(inserted, location).and_then(
112+
|inserted| {
113+
version_from_json_line(removed, location)
114+
.map(|removed| (removed, inserted))
115+
},
116+
) {
117+
Ok((removed, inserted)) => {
118+
if removed.yanked != inserted.yanked {
119+
self.changes.push(if inserted.yanked {
120+
Change::Yanked(inserted)
121+
} else {
122+
Change::Added(inserted)
123+
});
124+
}
125+
}
126+
Err(e) => {
127+
err = Some(e);
128+
break;
129+
}
130+
}
131+
}
132+
}
133+
(false, false) => {}
74134
}
75-
ChangeTag::Equal => {}
76-
}
135+
},
136+
);
137+
if let Some(err) = err {
138+
return Err(err.into());
77139
}
78140
}
79141
}

src/index/diff/mod.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::{Change, Index};
22
use git_repository as git;
33
use git_repository::prelude::ObjectIdExt;
4-
use git_repository::refs::transaction::PreviousValue;
54
use std::sync::atomic::AtomicBool;
65

76
mod delegate;
@@ -20,7 +19,9 @@ pub enum Error {
2019
#[error("Couldn't get the tree of a commit for diffing purposes")]
2120
PeelToTree(#[from] git::object::peel::to_kind::Error),
2221
#[error("Failed to diff two trees to find changed crates")]
23-
Diff(#[from] git::object::tree::diff::Error),
22+
Diff(#[from] git::object::blob::diff::init::Error),
23+
#[error(transparent)]
24+
DiffForEach(#[from] git::object::tree::diff::for_each::Error),
2425
#[error("Failed to decode {line:?} in file {file_name:?} as crate version")]
2526
VersionDecode {
2627
source: serde_json::Error,
@@ -70,11 +71,15 @@ impl Index {
7071
///
7172
/// Thus it is advised for the caller to run `git gc` occasionally based on their own requirements and usage patterns.
7273
// TODO: update this once it's clear how auto-gc works in `gitoxide`.
73-
pub fn peek_changes_with_options(
74+
pub fn peek_changes_with_options<P>(
7475
&self,
75-
progress: impl git::Progress,
76+
progress: P,
7677
should_interrupt: &AtomicBool,
77-
) -> Result<(Vec<Change>, git::hash::ObjectId), Error> {
78+
) -> Result<(Vec<Change>, git::hash::ObjectId), Error>
79+
where
80+
P: git::Progress,
81+
P::SubProgress: 'static,
82+
{
7883
let repo = &self.repo;
7984
let from = repo
8085
.find_reference(self.seen_ref_name)
@@ -203,11 +208,15 @@ impl Index {
203208
/// of the maximum number of open file handles as configured with `ulimit`.
204209
///
205210
/// Thus it is advised for the caller to run `git gc` occasionally based on their own requirements and usage patterns.
206-
pub fn fetch_changes_with_options(
211+
pub fn fetch_changes_with_options<P>(
207212
&self,
208-
progress: impl git::Progress,
213+
progress: P,
209214
should_interrupt: &AtomicBool,
210-
) -> Result<Vec<Change>, Error> {
215+
) -> Result<Vec<Change>, Error>
216+
where
217+
P: git::Progress,
218+
P::SubProgress: 'static,
219+
{
211220
let (changes, to) = self.peek_changes_with_options(progress, should_interrupt)?;
212221
self.set_last_seen_reference(to)?;
213222
Ok(changes)
@@ -219,7 +228,7 @@ impl Index {
219228
repo.reference(
220229
self.seen_ref_name,
221230
to,
222-
PreviousValue::Any,
231+
git::refs::transaction::PreviousValue::Any,
223232
"updating seen-ref head to latest fetched commit",
224233
)?;
225234
Ok(())

src/index/init.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::sync::atomic::AtomicBool;
99
#[allow(missing_docs)]
1010
pub enum Error {
1111
#[error(transparent)]
12-
PrepareClone(#[from] git::clone::prepare::Error),
12+
PrepareClone(#[from] git::clone::Error),
1313
#[error(transparent)]
1414
Fetch(#[from] git::clone::fetch::Error),
1515
#[error(transparent)]
@@ -40,12 +40,16 @@ impl Index {
4040
/// let index = Index::from_path_or_cloned_with_options(path, git::progress::Discard, &AtomicBool::default(), options)?;
4141
/// # Ok::<(), crates_index_diff::index::init::Error>(())
4242
/// ```
43-
pub fn from_path_or_cloned_with_options(
43+
pub fn from_path_or_cloned_with_options<P>(
4444
path: impl AsRef<Path>,
45-
progress: impl git::Progress,
45+
progress: P,
4646
should_interrupt: &AtomicBool,
4747
CloneOptions { url }: CloneOptions,
48-
) -> Result<Index, Error> {
48+
) -> Result<Index, Error>
49+
where
50+
P: git::Progress,
51+
P::SubProgress: 'static,
52+
{
4953
let path = path.as_ref();
5054
let mut repo = match git::open(path) {
5155
Ok(repo) => repo,

0 commit comments

Comments
 (0)