Skip to content

Commit 7314133

Browse files
committed
cargo dev crater: cleanup, don't re-download and reextract crates on every run
1 parent 734d205 commit 7314133

File tree

1 file changed

+52
-36
lines changed

1 file changed

+52
-36
lines changed

clippy_dev/src/crater.rs

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ struct KrateSource {
1313
struct Krate {
1414
version: String,
1515
name: String,
16+
// path to the extracted sources that clippy can check
1617
path: PathBuf,
1718
}
1819

@@ -23,37 +24,44 @@ impl KrateSource {
2324
name: name.into(),
2425
}
2526
}
27+
2628
fn download_and_extract(&self) -> Krate {
2729
let extract_dir = PathBuf::from("target/crater/crates");
28-
29-
// download
3030
let krate_download_dir = PathBuf::from("target/crater/downloads");
3131

32+
// url to download the crate from crates.io
3233
let url = format!(
3334
"https://crates.io/api/v1/crates/{}/{}/download",
3435
self.name, self.version
3536
);
36-
println!("Downloading {}, {} / {}", self.name, self.version, url);
37+
println!("Downloading and extracting {} {} from {}", self.name, self.version, url);
3738
let _ = std::fs::create_dir("target/crater/");
38-
3939
let _ = std::fs::create_dir(&krate_download_dir);
4040
let _ = std::fs::create_dir(&extract_dir);
4141

42-
let krate_name = format!("{}-{}.crate.tar.gz", &self.name, &self.version);
43-
let krate_file_path = krate_download_dir.join(krate_name);
44-
let mut krate_dest = std::fs::File::create(&krate_file_path).unwrap();
45-
let mut krate_req = ureq::get(&url).call().unwrap().into_reader();
46-
std::io::copy(&mut krate_req, &mut krate_dest).unwrap();
47-
// unzip the tarball
48-
let dl = std::fs::File::open(krate_file_path).unwrap();
49-
50-
let ungz_tar = flate2::read::GzDecoder::new(dl);
51-
// extract the tar archive
52-
let mut archiv = tar::Archive::new(ungz_tar);
53-
let extract_path = extract_dir.clone();
54-
archiv.unpack(&extract_path).expect("Failed to extract!");
55-
// extracted
56-
dbg!(&extract_path);
42+
let krate_file_path = krate_download_dir.join(format!("{}-{}.crate.tar.gz", &self.name, &self.version));
43+
// don't download/extract if we already have done so
44+
if !krate_file_path.is_file() {
45+
// create a file path to download and write the crate data into
46+
let mut krate_dest = std::fs::File::create(&krate_file_path).unwrap();
47+
let mut krate_req = ureq::get(&url).call().unwrap().into_reader();
48+
// copy the crate into the file
49+
std::io::copy(&mut krate_req, &mut krate_dest).unwrap();
50+
51+
// unzip the tarball
52+
let ungz_tar = flate2::read::GzDecoder::new(std::fs::File::open(&krate_file_path).unwrap());
53+
// extract the tar archive
54+
let mut archiv = tar::Archive::new(ungz_tar);
55+
archiv.unpack(&extract_dir).expect("Failed to extract!");
56+
57+
// unzip the tarball
58+
let ungz_tar = flate2::read::GzDecoder::new(std::fs::File::open(&krate_file_path).unwrap());
59+
// extract the tar archive
60+
let mut archiv = tar::Archive::new(ungz_tar);
61+
archiv.unpack(&extract_dir).expect("Failed to extract!");
62+
}
63+
// crate is extracted, return a new Krate object which contains the path to the extracted
64+
// sources that clippy can check
5765
Krate {
5866
version: self.version.clone(),
5967
name: self.name.clone(),
@@ -64,24 +72,37 @@ impl KrateSource {
6472

6573
impl Krate {
6674
fn run_clippy_lints(&self, cargo_clippy_path: &PathBuf) -> Vec<String> {
75+
println!("Linting {} {}...", &self.name, &self.version);
6776
let cargo_clippy_path = std::fs::canonicalize(cargo_clippy_path).unwrap();
68-
let project_root = &self.path;
69-
dbg!(&cargo_clippy_path);
70-
dbg!(&project_root);
7177

72-
let output = std::process::Command::new(cargo_clippy_path)
78+
let all_output = std::process::Command::new(cargo_clippy_path)
79+
// lint warnings will look like this:
80+
// src/cargo/ops/cargo_compile.rs:127:35: warning: usage of `FromIterator::from_iter`
7381
.args(&["--", "--message-format=short", "--", "--cap-lints=warn"])
74-
.current_dir(project_root)
82+
.current_dir(&self.path)
7583
.output()
7684
.unwrap();
77-
let mut output = String::from_utf8_lossy(&output.stderr);
78-
let output: Vec<&str> = output.lines().collect();
79-
let mut output: Vec<String> = output
85+
let stderr = String::from_utf8_lossy(&all_output.stderr);
86+
let output_lines = stderr.lines();
87+
let mut output: Vec<String> = output_lines
8088
.into_iter()
8189
.filter(|line| line.contains(": warning: "))
82-
.map(|l| l.to_string())
90+
// prefix with the crate name and version
91+
// cargo-0.49.0/src/cargo/ops/cargo_compile.rs:127:35: warning: usage of `FromIterator::from_iter`
92+
.map(|line| format!("{}-{}/{}", self.name, self.version, line))
93+
// remove the "warning: "
94+
.map(|line| {
95+
let remove_pat = "warning: ";
96+
let pos = line
97+
.find(&remove_pat)
98+
.expect("clippy output did not contain \"warning: \"");
99+
let mut new = line[0..pos].to_string();
100+
new.push_str(&line[pos + remove_pat.len()..]);
101+
new
102+
})
83103
.collect();
84104

105+
// sort messages alphabtically to avoid noise in the logs
85106
output.sort();
86107
output
87108
}
@@ -97,7 +118,6 @@ fn build_clippy() {
97118
// the main fn
98119
pub fn run() {
99120
let cargo_clippy_path: PathBuf = PathBuf::from("target/debug/cargo-clippy");
100-
let clippy_driver_path: PathBuf = PathBuf::from("target/debug/clippy-driver");
101121

102122
// crates we want to check:
103123
let krates: Vec<KrateSource> = vec![KrateSource::new("regex", "1.4.2"), KrateSource::new("cargo", "0.49.0")];
@@ -112,11 +132,6 @@ pub fn run() {
112132
"target/debug/cargo-clippy binary not found! {}",
113133
cargo_clippy_path.display()
114134
);
115-
assert!(
116-
clippy_driver_path.is_file(),
117-
"target/debug/clippy-driver binary not found! {}",
118-
clippy_driver_path.display()
119-
);
120135

121136
// download and extract the crates, then run clippy on them and collect clippys warnings
122137
let clippy_lint_results: Vec<Vec<String>> = krates
@@ -125,7 +140,8 @@ pub fn run() {
125140
.map(|krate| krate.run_clippy_lints(&cargo_clippy_path))
126141
.collect();
127142

128-
let results: Vec<String> = clippy_lint_results.into_iter().flatten().collect();
143+
let all_warnings: Vec<String> = clippy_lint_results.into_iter().flatten().collect();
129144

130-
results.iter().for_each(|l| println!("{}", l));
145+
// TODO: save these into a file
146+
all_warnings.iter().for_each(|l| println!("{}", l));
131147
}

0 commit comments

Comments
 (0)