Skip to content

Commit e2a2959

Browse files
committed
Use crates-index instead of rewriting it
This is possible now that it supports bare checkouts. This also takes the liberty of iterating the crates in parallel, which should give a nice speedup.
1 parent 2b52011 commit e2a2959

File tree

5 files changed

+24
-66
lines changed

5 files changed

+24
-66
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ exclude = [
1616
]
1717

1818
[features]
19-
consistency_check = ["crates-index"]
19+
consistency_check = ["crates-index", "rayon"]
2020

2121
[dependencies]
2222
sentry = "0.24.1"
@@ -27,6 +27,7 @@ log = "0.4"
2727
regex = "1"
2828
structopt = "0.3"
2929
crates-index = { version = "0.18.5", optional = true }
30+
rayon = { version = "1", optional = true }
3031
crates-index-diff = "8.0.0"
3132
reqwest = { version = "0.11", features = ["blocking", "json"] } # TODO: Remove blocking when async is ready
3233
semver = { version = "1.0.4", features = ["serde"] }

src/index/crates.rs

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +0,0 @@
1-
use anyhow::Context;
2-
use crates_index::Crate;
3-
pub(crate) struct Crates {
4-
repo: git2::Repository,
5-
}
6-
7-
impl Crates {
8-
pub(super) fn new(repo: git2::Repository) -> Self {
9-
Self { repo }
10-
}
11-
12-
pub(crate) fn walk(&self, mut f: impl FnMut(Crate)) -> Result<(), anyhow::Error> {
13-
log::debug!("Walking crates in index");
14-
let tree = self
15-
.repo
16-
.find_commit(self.repo.refname_to_id("refs/remotes/origin/master")?)?
17-
.tree()?;
18-
19-
let mut result = Ok(());
20-
21-
tree.walk(git2::TreeWalkMode::PreOrder, |_, entry| {
22-
result = (|| {
23-
if let Some(blob) = entry.to_object(&self.repo)?.as_blob() {
24-
if let Ok(krate) = Crate::from_slice(blob.content()) {
25-
f(krate);
26-
} else {
27-
log::warn!("not a crate '{}'", entry.name().unwrap());
28-
}
29-
}
30-
Result::<(), anyhow::Error>::Ok(())
31-
})()
32-
.with_context(|| {
33-
format!(
34-
"loading crate details from '{}'",
35-
entry.name().unwrap_or("<unknown>")
36-
)
37-
});
38-
match result {
39-
Ok(_) => git2::TreeWalkResult::Ok,
40-
Err(_) => git2::TreeWalkResult::Abort,
41-
}
42-
})?;
43-
44-
result
45-
}
46-
}

src/index/mod.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ use crate::error::Result;
88
use crate::utils::report_error;
99

1010
pub(crate) mod api;
11-
#[cfg(feature = "consistency_check")]
12-
mod crates;
1311

1412
pub struct Index {
1513
path: PathBuf,
@@ -89,15 +87,18 @@ impl Index {
8987
}
9088

9189
#[cfg(feature = "consistency_check")]
92-
pub(crate) fn crates(&self) -> Result<crates::Crates> {
90+
pub(crate) fn crates(&self) -> Result<crates_index::Index> {
9391
// First ensure the index is up to date, peeking will pull the latest changes without
9492
// affecting anything else.
9593
log::debug!("Updating index");
9694
self.diff()?.peek_changes()?;
97-
// It'd be nice to use `crates_index` directly for interacting with the index, but it
98-
// doesn't support bare repositories. So we use its `Crate` type but walk the index
99-
// ourselves.
100-
Ok(crates::Crates::new(git2::Repository::open(&self.path)?))
95+
log::debug!("Opening with `crates_index`");
96+
// crates_index requires the repo url to match the existing origin or it tries to reinitialize the repo
97+
let repo_url = self
98+
.repository_url
99+
.as_deref()
100+
.unwrap_or("https://github.com/rust-lang/crates.io-index");
101+
crates_index::Index::with_path(&self.path, repo_url).map_err(Into::into)
101102
}
102103

103104
pub fn api(&self) -> &Api {

src/utils/consistency/index.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
use super::data::{Crate, CrateName, Data, Release, Version};
22
use crate::Index;
3+
use rayon::iter::ParallelIterator;
34

45
pub(crate) fn load(index: &Index) -> Result<Data, anyhow::Error> {
5-
let mut data = Data::default();
6-
7-
index.crates()?.walk(|krate| {
8-
data.crates.insert(
9-
CrateName(krate.name().into()),
10-
Crate {
11-
releases: krate
6+
let crates = index
7+
.crates()?
8+
.crates_parallel()
9+
.map(|krate| {
10+
krate.map(|krate| {
11+
let releases = krate
1212
.versions()
1313
.iter()
1414
.map(|version| (Version(version.version().into()), Release::default()))
15-
.collect(),
16-
},
17-
);
18-
})?;
15+
.collect();
16+
(CrateName(krate.name().into()), Crate { releases })
17+
})
18+
})
19+
.collect::<Result<_, _>>()?;
1920

20-
Ok(data)
21+
Ok(Data { crates })
2122
}

0 commit comments

Comments
 (0)