1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
use std::collections::HashMap;
use crate_db::builddb::*;
mod parse;
use kitchen_sink::*;
use parse::*;
use std::path::Path;
use std::process::Command;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let crates = kitchen_sink::KitchenSink::new_default()?;
let db = BuildDb::new(crates.main_cache_dir().join("builds.db"))?;
let docker_root = crates.main_cache_dir().join("docker");
prepare_docker(&docker_root)?;
let filter = std::env::args().skip(1).next();
for (_, all) in crates.all_crates_io_crates() {
if stopped() {
break;
}
if let Some(f) = &filter {
if !all.name().contains(f) {
continue;
}
}
if let Err(e) = analyze_crate(&all, &db, &crates, &docker_root) {
eprintln!("•• {}: {}", all.name(), e);
continue;
}
}
Ok(())
}
fn analyze_crate(all: &CratesIndexCrate, db: &BuildDb, crates: &KitchenSink, docker_root: &Path) -> Result<(), Box<dyn std::error::Error>> {
let ref origin = Origin::from_crates_io_name(all.name());
let compat_info = db.get_compat(origin)?;
// look for missing 1.24 tests (ignoring the "probably" ones that aren't authoritative)
if compat_info.iter().any(|c| c.compat != Compat::ProbablyWorks && c.crate_version.minor == 24) {
println!("{} got it {:?}", all.name(), compat_info);
return Ok(());
}
println!("checking {}", all.name());
let ver = all.latest_version();
let (stdout, stderr) = do_builds(&crates, &all, &docker_root)?;
println!("{}\n{}\n", stdout, stderr);
db.set_raw_build_info(origin, ver.version(), &stdout, &stderr)?;
for f in parse_analyses(&stdout, &stderr) {
println!("{:#?}", f);
if let Some(rustc_version) = f.rustc_version {
for (rustc_override, name, version, compat) in f.crates {
let rustc_version = rustc_override.unwrap_or(&rustc_version);
let certain = rustc_override.is_some(); // that's for 2018 edition
db.set_compat(&Origin::from_crates_io_name(&name), &version, rustc_version, compat, certain)?;
}
}
}
Ok(())
}
fn prepare_docker(docker_root: &Path) -> Result<(), Box<dyn std::error::Error>> {
let res = Command::new("docker")
.current_dir(docker_root)
.arg("build")
.arg("-t").arg("testing1")
.arg(".")
.status()?;
if !res.success() {
Err("failed build")?;
}
Ok(())
}
fn do_builds(_crates: &KitchenSink, all: &CratesIndexCrate, docker_root: &Path) -> Result<(String, String), Box<dyn std::error::Error>> {
let mut versions = HashMap::new();
for ver in all.versions().iter().filter(|v| !v.is_yanked()).filter_map(|v| SemVer::parse(v.version()).ok()) {
let unstable = ver.major == 0;
let major = if unstable {ver.minor} else {ver.major};
versions.insert((unstable, major), ver); // later wins
}
let mut cmd = Command::new("docker");
cmd
.current_dir(docker_root)
.arg("run")
.arg("--rm")
.arg("-m1500m")
.arg("testing1")
.arg("/tmp/run-crate-tests.sh");
for ver in versions.values().take(15) {
cmd.arg(format!("{}=\"{}\"\n", all.name(), ver));
}
let out = cmd
.output()?;
let stdout = String::from_utf8_lossy(&out.stdout).into_owned();
let mut stderr = String::from_utf8_lossy(&out.stderr).into_owned();
if !out.status.success() {
stderr += "\nexit failure\n";
}
Ok((stdout, stderr))
}
|