Skip to content

Commit aba9087

Browse files
committed
Merge branch 'syphar-handle-crate-delets'
2 parents 0301da5 + df91215 commit aba9087

File tree

6 files changed

+101
-116
lines changed

6 files changed

+101
-116
lines changed

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ readme = "changelog.md"
1212
include = ["src/**/*", "LICENSE.md", "README.md", "CHANGELOG.md"]
1313

1414
[dependencies]
15-
serde = "1"
16-
serde_derive = "1"
15+
serde = { version = "1", features = ["std", "derive"] }
1716
serde_json = "1"
1817

1918
[dependencies.git2]

src/index.rs

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
use super::CrateVersion;
2-
use serde_json;
1+
use super::{Change, CrateVersion};
32
use std::path::Path;
43

54
use git2::{
6-
build::RepoBuilder, Delta, DiffFormat, Error as GitError, ErrorClass, Object, ObjectType, Oid,
7-
Reference, Repository, Tree,
5+
build::RepoBuilder, Delta, Error as GitError, ErrorClass, Object, ObjectType, Oid, Reference,
6+
Repository, Tree,
87
};
98
use std::str;
109

@@ -24,7 +23,9 @@ pub struct Index {
2423

2524
/// Options for use in `Index::from_path_or_cloned_with_options`
2625
pub struct CloneOptions<'a> {
26+
/// The url from which the repository should be cloned.
2727
pub repository_url: String,
28+
/// Git2 fetch options to control exactly how to clone.
2829
pub fetch_options: Option<git2::FetchOptions<'a>>,
2930
}
3031

@@ -44,7 +45,7 @@ impl Index {
4445
}
4546

4647
/// Return the reference pointing to the state we have seen after calling `fetch_changes()`.
47-
pub fn last_seen_reference(&self) -> Result<Reference, GitError> {
48+
pub fn last_seen_reference(&self) -> Result<Reference<'_>, GitError> {
4849
self.repo.find_reference(self.seen_ref_name)
4950
}
5051

@@ -103,7 +104,7 @@ impl Index {
103104
CloneOptions {
104105
repository_url,
105106
fetch_options,
106-
}: CloneOptions,
107+
}: CloneOptions<'_>,
107108
) -> Result<Index, GitError> {
108109
let mut repo_did_exist = true;
109110
let repo = Repository::open(path.as_ref()).or_else(|err| {
@@ -147,11 +148,11 @@ impl Index {
147148
}
148149

149150
/// As `peek_changes_with_options`, but without the options.
150-
pub fn peek_changes(&self) -> Result<(Vec<CrateVersion>, git2::Oid), GitError> {
151+
pub fn peek_changes(&self) -> Result<(Vec<Change>, git2::Oid), GitError> {
151152
self.peek_changes_with_options(None)
152153
}
153154

154-
/// Return all `CrateVersion`s that are observed between the last time `fetch_changes(…)` was called
155+
/// Return all `Change`s that are observed between the last time `fetch_changes(…)` was called
155156
/// and the latest state of the `crates.io` index repository, which is obtained by fetching
156157
/// the remote called `origin`.
157158
/// The `last_seen_reference()` will not be created or updated.
@@ -169,7 +170,7 @@ impl Index {
169170
pub fn peek_changes_with_options(
170171
&self,
171172
options: Option<&mut git2::FetchOptions<'_>>,
172-
) -> Result<(Vec<CrateVersion>, git2::Oid), GitError> {
173+
) -> Result<(Vec<Change>, git2::Oid), GitError> {
173174
let from = self
174175
.last_seen_reference()
175176
.and_then(|r| {
@@ -186,9 +187,7 @@ impl Index {
186187
None,
187188
)
188189
})?;
189-
let latest_fetched_commit_oid =
190-
self.repo.refname_to_id("refs/remotes/origin/master")?;
191-
latest_fetched_commit_oid
190+
self.repo.refname_to_id("refs/remotes/origin/master")?
192191
};
193192

194193
Ok((
@@ -201,11 +200,11 @@ impl Index {
201200
}
202201

203202
/// As `fetch_changes_with_options`, but without the options.
204-
pub fn fetch_changes(&self) -> Result<Vec<CrateVersion>, GitError> {
203+
pub fn fetch_changes(&self) -> Result<Vec<Change>, GitError> {
205204
self.fetch_changes_with_options(None)
206205
}
207206

208-
/// Return all `CrateVersion`s that are observed between the last time this method was called
207+
/// Return all `Change`s that are observed between the last time this method was called
209208
/// and the latest state of the `crates.io` index repository, which is obtained by fetching
210209
/// the remote called `origin`.
211210
/// The `last_seen_reference()` will be created or adjusted to point to the latest fetched
@@ -221,7 +220,7 @@ impl Index {
221220
pub fn fetch_changes_with_options(
222221
&self,
223222
options: Option<&mut git2::FetchOptions<'_>>,
224-
) -> Result<Vec<CrateVersion>, GitError> {
223+
) -> Result<Vec<Change>, GitError> {
225224
let (changes, to) = self.peek_changes_with_options(options)?;
226225
self.set_last_seen_reference(to)?;
227226
Ok(changes)
@@ -253,7 +252,7 @@ impl Index {
253252
&self,
254253
from: impl AsRef<str>,
255254
to: impl AsRef<str>,
256-
) -> Result<Vec<CrateVersion>, GitError> {
255+
) -> Result<Vec<Change>, GitError> {
257256
self.changes_from_objects(
258257
&self.repo.revparse_single(from.as_ref())?,
259258
&self.repo.revparse_single(to.as_ref())?,
@@ -264,10 +263,10 @@ impl Index {
264263
/// to either `Commit`s or `Tree`s.
265264
pub fn changes_from_objects(
266265
&self,
267-
from: &Object,
268-
to: &Object,
269-
) -> Result<Vec<CrateVersion>, GitError> {
270-
fn into_tree<'a>(repo: &'a Repository, obj: &Object) -> Result<Tree<'a>, GitError> {
266+
from: &Object<'_>,
267+
to: &Object<'_>,
268+
) -> Result<Vec<Change>, GitError> {
269+
fn into_tree<'a>(repo: &'a Repository, obj: &Object<'_>) -> Result<Tree<'a>, GitError> {
271270
repo.find_tree(match obj.kind() {
272271
Some(ObjectType::Commit) => obj
273272
.as_commit()
@@ -285,24 +284,43 @@ impl Index {
285284
Some(&into_tree(&self.repo, to)?),
286285
None,
287286
)?;
288-
let mut res: Vec<CrateVersion> = Vec::new();
289-
diff.print(DiffFormat::Patch, |delta, _, diffline| {
290-
if diffline.origin() != LINE_ADDED_INDICATOR {
291-
return true;
292-
}
287+
let mut changes: Vec<Change> = Vec::new();
288+
let mut deletes: Vec<String> = Vec::new();
289+
diff.foreach(
290+
&mut |delta, _| {
291+
if delta.status() == Delta::Deleted {
292+
if let Some(path) = delta.new_file().path() {
293+
if let Some(file_name) = path.file_name() {
294+
deletes.push(file_name.to_string_lossy().to_string());
295+
}
296+
}
297+
}
298+
true
299+
},
300+
None,
301+
None,
302+
Some(&mut |delta, _hunk, diffline| {
303+
if diffline.origin() != LINE_ADDED_INDICATOR {
304+
return true;
305+
}
306+
if !matches!(delta.status(), Delta::Added | Delta::Modified) {
307+
return true;
308+
}
293309

294-
if !match delta.status() {
295-
Delta::Added | Delta::Modified => true,
296-
_ => false,
297-
} {
298-
return true;
299-
}
310+
if let Ok(crate_version) =
311+
serde_json::from_slice::<CrateVersion>(diffline.content())
312+
{
313+
if crate_version.yanked {
314+
changes.push(Change::Yanked(crate_version));
315+
} else {
316+
changes.push(Change::Added(crate_version));
317+
}
318+
}
319+
true
320+
}),
321+
)?;
300322

301-
if let Ok(c) = serde_json::from_slice(diffline.content()) {
302-
res.push(c)
303-
}
304-
true
305-
})
306-
.map(|_| res)
323+
changes.extend(deletes.iter().map(|krate| Change::Deleted(krate.clone())));
324+
Ok(changes)
307325
}
308326
}

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
//!
33
//! Have a look at the real-world usage to learn more about it:
44
//! [crates-io-cli](https://github.com/Byron/crates-io-cli-rs/blob/b7a39ad8ef68adb81b2d8a7e552cb0a2a73f7d5b/src/main.rs#L62)
5-
#[macro_use]
6-
extern crate serde_derive;
5+
#![forbid(missing_docs)]
6+
#![deny(rust_2018_idioms)]
77

88
mod index;
99
mod version;

src/version.rs

Lines changed: 16 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,39 @@
1-
use serde::de::{Deserialize, Deserializer};
2-
use serde::ser::{Serialize, Serializer};
31
use std::collections::HashMap;
42

53
use std::fmt;
64

75
/// Identify a kind of change that occurred to a crate
8-
#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Debug)]
9-
pub enum ChangeKind {
10-
/// A crate version was added
11-
Added,
6+
#[derive(Clone, Eq, PartialEq, Debug)]
7+
pub enum Change {
128
/// A crate version was added or it was unyanked.
13-
Yanked,
9+
Added(CrateVersion),
10+
/// A crate version was yanked.
11+
Yanked(CrateVersion),
12+
/// A crate was deleted
13+
Deleted(String),
1414
}
1515

16-
impl Default for ChangeKind {
17-
fn default() -> Self {
18-
ChangeKind::Added
19-
}
20-
}
21-
22-
impl<'de> Deserialize<'de> for ChangeKind {
23-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
24-
where
25-
D: Deserializer<'de>,
26-
{
27-
struct Visitor;
28-
impl<'de> ::serde::de::Visitor<'de> for Visitor {
29-
type Value = ChangeKind;
30-
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
31-
formatter.write_str("boolean")
32-
}
33-
fn visit_bool<E>(self, value: bool) -> Result<ChangeKind, E>
34-
where
35-
E: ::serde::de::Error,
36-
{
37-
if value {
38-
Ok(ChangeKind::Yanked)
39-
} else {
40-
Ok(ChangeKind::Added)
41-
}
42-
}
43-
}
44-
deserializer.deserialize_bool(Visitor)
45-
}
46-
}
47-
48-
impl Serialize for ChangeKind {
49-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
50-
where
51-
S: Serializer,
52-
{
53-
serializer.serialize_bool(self == &ChangeKind::Yanked)
54-
}
55-
}
56-
57-
impl fmt::Display for ChangeKind {
58-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16+
impl fmt::Display for Change {
17+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5918
write!(
6019
f,
6120
"{}",
6221
match *self {
63-
ChangeKind::Added => "added",
64-
ChangeKind::Yanked => "yanked",
22+
Change::Added(_) => "added",
23+
Change::Yanked(_) => "yanked",
24+
Change::Deleted(_) => "deleted",
6525
}
6626
)
6727
}
6828
}
6929

7030
/// Pack all information we know about a change made to a version of a crate.
71-
#[derive(Clone, Serialize, Deserialize, Eq, PartialEq, Debug)]
31+
#[derive(Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq, Debug)]
7232
pub struct CrateVersion {
7333
/// The crate name, i.e. `clap`.
7434
pub name: String,
75-
/// The kind of change.
76-
#[serde(rename = "yanked")]
77-
pub kind: ChangeKind,
35+
/// is the release yanked?
36+
pub yanked: bool,
7837
/// The semantic version of the crate.
7938
#[serde(rename = "vers")]
8039
pub version: String,
@@ -89,7 +48,7 @@ pub struct CrateVersion {
8948
}
9049

9150
/// A single dependency of a specific crate version
92-
#[derive(Clone, Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq, Debug)]
51+
#[derive(Clone, serde::Serialize, serde::Deserialize, Ord, PartialOrd, Eq, PartialEq, Debug)]
9352
pub struct Dependency {
9453
/// The crate name
9554
pub name: String,

0 commit comments

Comments
 (0)