Skip to content

Commit bf70732

Browse files
committed
Auto merge of #519 - Zeegomo:detect-build-errors, r=pietroalbini
Detect build errors This pr introduces a bunch of changes aimed to better inspect crate build failure. In particular it detects build error codes and dependencies using two new variants `FailureReason::CompilerError` and `FailureReason::DependsOn`.
2 parents c3f462b + 4227bc1 commit bf70732

File tree

23 files changed

+1154
-240
lines changed

23 files changed

+1154
-240
lines changed

Cargo.lock

Lines changed: 595 additions & 163 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
@@ -63,11 +63,12 @@ hmac = "0.7"
6363
sha-1 = "0.8"
6464
rust_team_data = { git = "https://github.com/rust-lang/team" }
6565
systemstat = "0.1.4"
66-
rustwide = { version = "0.6.1", features = ["unstable"] }
66+
rustwide = { version = "0.8.0", features = ["unstable"] }
6767
percent-encoding = "2.1.0"
6868
remove_dir_all = "0.5.2"
6969
ctrlc = "3.1.3"
7070
prometheus = "0.7.0"
71+
cargo_metadata = "0.9.1"
7172

7273
[dev-dependencies]
7374
assert_cmd = "0.10.1"

local-crates/faulty-deps/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "faulty-deps"
3+
version = "0.1.0"
4+
authors = ["Giacomo Pasini <g.pasini98@gmail.com>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
error_code = {git = "https://github.com/rust-lang/crater", rev = "c3f462bdab37a93c24b2b172b90564749e892cbc"}
9+
lazy_static = "=0.1.0"

local-crates/faulty-deps/src/main.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
use error_code::STRING;
2+
3+
fn main() {
4+
println!("Hello, world!");
5+
}

src/actions/experiments/edit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ impl Action for EditExperiment {
153153
if let Some(requirement) = self.requirement {
154154
let changes = t.execute(
155155
"UPDATE experiments SET requirement = ?1 WHERE name = ?2;",
156-
&[&requirement.to_string(), &self.name],
156+
&[&requirement, &self.name],
157157
)?;
158158
assert_eq!(changes, 1);
159159
ex.requirement = Some(requirement);

src/agent/api.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ impl AgentApi {
150150
krate: &Crate,
151151
toolchain: &Toolchain,
152152
log: &[u8],
153-
result: TestResult,
153+
result: &TestResult,
154154
version: Option<(&Crate, &Crate)>,
155155
) -> Fallible<()> {
156156
self.retry(|this| {

src/agent/results.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl<'a> WriteResults for ResultsUploader<'a> {
8686
updated.as_ref().unwrap_or(krate),
8787
toolchain,
8888
output.as_bytes(),
89-
result,
89+
&result,
9090
new_version.map(|new| (krate, new)),
9191
)?;
9292

src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ impl Config {
114114
Crate::Registry(ref details) => self.crates.get(&details.name),
115115
Crate::GitHub(ref repo) => self.github_repos.get(&repo.slug()),
116116
Crate::Local(ref name) => self.local_crates.get(name),
117+
Crate::Git(_) | Crate::Path(_) => unimplemented!("unsupported crate"),
117118
}
118119
}
119120

src/crates/lists.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ pub(crate) fn get_crates(
9696
Crate::Registry(RegistryCrate { ref name, .. }) => demo_registry.remove(name),
9797
Crate::GitHub(ref repo) => demo_github.remove(&repo.slug()),
9898
Crate::Local(ref name) => demo_local.remove(name),
99+
Crate::Git(_) | Crate::Path(_) => unimplemented!("unsupported crate"),
99100
};
100101

101102
if add {

src/crates/mod.rs

Lines changed: 181 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,30 @@ mod sources;
33

44
use crate::dirs::LOCAL_CRATES_DIR;
55
use crate::prelude::*;
6+
use cargo_metadata::PackageId;
7+
use percent_encoding::{percent_decode_str, utf8_percent_encode, NON_ALPHANUMERIC};
68
use rustwide::Crate as RustwideCrate;
9+
use std::convert::TryFrom;
710
use std::fmt;
11+
use std::path::Path;
812
use std::str::FromStr;
913

1014
pub(crate) use crate::crates::sources::github::GitHubRepo;
1115
pub(crate) use crate::crates::sources::registry::RegistryCrate;
1216

17+
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, Clone)]
18+
pub struct GitRepo {
19+
pub url: String,
20+
pub sha: Option<String>,
21+
}
22+
1323
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, Clone)]
1424
pub enum Crate {
1525
Registry(RegistryCrate),
1626
GitHub(GitHubRepo),
1727
Local(String),
28+
Path(String),
29+
Git(GitRepo),
1830
}
1931

2032
impl Crate {
@@ -29,6 +41,20 @@ impl Crate {
2941
}
3042
}
3143
Crate::Local(ref name) => format!("local/{}", name),
44+
Crate::Path(ref path) => {
45+
format!("path/{}", utf8_percent_encode(&path, &NON_ALPHANUMERIC))
46+
}
47+
Crate::Git(ref repo) => {
48+
if let Some(ref sha) = repo.sha {
49+
format!(
50+
"git/{}/{}",
51+
utf8_percent_encode(&repo.url, &NON_ALPHANUMERIC),
52+
sha
53+
)
54+
} else {
55+
format!("git/{}", utf8_percent_encode(&repo.url, &NON_ALPHANUMERIC),)
56+
}
57+
}
3258
}
3359
}
3460

@@ -39,6 +65,60 @@ impl Crate {
3965
RustwideCrate::git(&format!("https://github.com/{}/{}", repo.org, repo.name))
4066
}
4167
Self::Local(name) => RustwideCrate::local(&LOCAL_CRATES_DIR.join(name)),
68+
Self::Path(path) => RustwideCrate::local(Path::new(&path)),
69+
Self::Git(repo) => RustwideCrate::git(&repo.url),
70+
}
71+
}
72+
}
73+
74+
impl TryFrom<&'_ PackageId> for Crate {
75+
type Error = failure::Error;
76+
77+
fn try_from(pkgid: &PackageId) -> Fallible<Crate> {
78+
let parts = &pkgid
79+
.repr
80+
.split_ascii_whitespace()
81+
.flat_map(|s| {
82+
// remove ()
83+
s.trim_matches(|c: char| c.is_ascii_punctuation())
84+
// split resource and protocol
85+
.split('+')
86+
})
87+
.collect::<Vec<_>>();
88+
89+
match parts[..] {
90+
[name, version, "registry", _] => Ok(Crate::Registry(RegistryCrate {
91+
name: name.to_string(),
92+
version: version.to_string(),
93+
})),
94+
[_, _, "path", path] => Ok(Crate::Path(path.to_string())),
95+
[_, _, "git", repo] => {
96+
if repo.starts_with("https://github.com") {
97+
Ok(Crate::GitHub(repo.replace("#", "/").parse()?))
98+
} else {
99+
let mut parts = repo.split('#').rev().collect::<Vec<_>>();
100+
let url = parts.pop();
101+
let sha = parts.pop();
102+
103+
match (url, sha) {
104+
(Some(url), None) => Ok(Crate::Git(GitRepo {
105+
url: url.to_string(),
106+
sha: None,
107+
})),
108+
(Some(url), Some(sha)) => Ok(Crate::Git(GitRepo {
109+
// remove additional queries if the sha is present
110+
// as the crate version is already uniquely determined
111+
url: url.split('?').next().unwrap().to_string(),
112+
sha: Some(sha.to_string()),
113+
})),
114+
_ => bail!("malformed git repo: {}", repo),
115+
}
116+
}
117+
}
118+
_ => bail!(
119+
"malformed pkgid format: {}\n maybe the representation has changed?",
120+
pkgid.repr
121+
),
42122
}
43123
}
44124
}
@@ -50,8 +130,25 @@ impl fmt::Display for Crate {
50130
"{}",
51131
match *self {
52132
Crate::Registry(ref krate) => format!("{}-{}", krate.name, krate.version),
53-
Crate::GitHub(ref repo) => repo.slug(),
133+
Crate::GitHub(ref repo) =>
134+
if let Some(ref sha) = repo.sha {
135+
format!("{}/{}/{}", repo.org, repo.name, sha)
136+
} else {
137+
format!("{}/{}", repo.org, repo.name)
138+
},
54139
Crate::Local(ref name) => format!("{} (local)", name),
140+
Crate::Path(ref path) =>
141+
format!("{}", utf8_percent_encode(path, &NON_ALPHANUMERIC)),
142+
Crate::Git(ref repo) =>
143+
if let Some(ref sha) = repo.sha {
144+
format!(
145+
"{}/{}",
146+
utf8_percent_encode(&repo.url, &NON_ALPHANUMERIC),
147+
sha
148+
)
149+
} else {
150+
utf8_percent_encode(&repo.url, &NON_ALPHANUMERIC).to_string()
151+
},
55152
}
56153
)
57154
}
@@ -77,17 +174,94 @@ impl FromStr for Crate {
77174
name: name.to_string(),
78175
sha: None,
79176
})),
177+
["git", repo, sha] => Ok(Crate::Git(GitRepo {
178+
url: percent_decode_str(repo).decode_utf8()?.to_string(),
179+
sha: Some(sha.to_string()),
180+
})),
181+
["git", repo] => Ok(Crate::Git(GitRepo {
182+
url: percent_decode_str(repo).decode_utf8()?.to_string(),
183+
sha: None,
184+
})),
80185
["local", name] => Ok(Crate::Local(name.to_string())),
186+
["path", path] => Ok(Crate::Path(
187+
percent_decode_str(path).decode_utf8()?.to_string(),
188+
)),
81189
_ => bail!("unexpected crate value"),
82190
}
83191
}
84192
}
85193

86194
#[cfg(test)]
87195
mod tests {
88-
use super::{Crate, GitHubRepo, RegistryCrate};
196+
use super::{Crate, GitHubRepo, GitRepo, RegistryCrate};
197+
use cargo_metadata::PackageId;
198+
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
199+
use std::convert::TryFrom;
89200
use std::str::FromStr;
90201

202+
macro_rules! test_from_pkgid {
203+
($($str:expr => $rust:expr,)*) => {
204+
$(
205+
let pkgid = PackageId {
206+
repr: $str.to_string(),
207+
};
208+
209+
assert_eq!(Crate::try_from(&pkgid).unwrap(), $rust);
210+
)*
211+
};
212+
}
213+
214+
#[test]
215+
fn test_parse_from_pkgid() {
216+
test_from_pkgid! {
217+
"dummy 0.1.0 (path+file:///opt/rustwide/workdir)" => Crate::Path("file:///opt/rustwide/workdir".to_string()),
218+
"dummy 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" => Crate::Registry(RegistryCrate {
219+
name: "dummy".to_string(),
220+
version: "0.1.0".to_string()
221+
}),
222+
"dummy 0.1.0 (git+https://github.com/dummy_org/dummy#9823f01cf4948a41279f6a3febcf793130cab4f6)" => Crate::GitHub(GitHubRepo {
223+
org: "dummy_org".to_string(),
224+
name: "dummy".to_string(),
225+
sha: Some("9823f01cf4948a41279f6a3febcf793130cab4f6".to_string())
226+
}),
227+
"dummy 0.1.0 (git+https://github.com/dummy_org/dummy?rev=dummyrev#9823f01cf4948a41279f6a3febcf793130cab4f6)" => Crate::GitHub(GitHubRepo {
228+
org: "dummy_org".to_string(),
229+
name: "dummy".to_string(),
230+
sha: Some("9823f01cf4948a41279f6a3febcf793130cab4f6".to_string())
231+
}),
232+
"dummy 0.1.0 (git+https://github.com/dummy_org/dummy)" => Crate::GitHub(GitHubRepo {
233+
org: "dummy_org".to_string(),
234+
name: "dummy".to_string(),
235+
sha: None
236+
}),
237+
"dummy 0.1.0 (git+https://gitlab.com/dummy_org/dummy#9823f01cf4948a41279f6a3febcf793130cab4f6)" => Crate::Git(GitRepo {
238+
url: "https://gitlab.com/dummy_org/dummy"
239+
.to_string(),
240+
sha: Some("9823f01cf4948a41279f6a3febcf793130cab4f6".to_string())
241+
}),
242+
"dummy 0.1.0 (git+https://gitlab.com/dummy_org/dummy?branch=dummybranch#9823f01cf4948a41279f6a3febcf793130cab4f6)" => Crate::Git(GitRepo {
243+
url: "https://gitlab.com/dummy_org/dummy"
244+
.to_string(),
245+
sha: Some("9823f01cf4948a41279f6a3febcf793130cab4f6".to_string())
246+
}),
247+
"dummy 0.1.0 (git+https://gitlab.com/dummy_org/dummy)" => Crate::Git(GitRepo {
248+
url: "https://gitlab.com/dummy_org/dummy"
249+
.to_string(),
250+
sha: None
251+
}),
252+
"dummy 0.1.0 (git+https://gitlab.com/dummy_org/dummy?branch=dummybranch)" => Crate::Git(GitRepo {
253+
url: "https://gitlab.com/dummy_org/dummy?branch=dummybranch"
254+
.to_string(),
255+
sha: None
256+
}),
257+
}
258+
259+
assert!(Crate::try_from(&PackageId {
260+
repr: "invalid".to_string()
261+
})
262+
.is_err());
263+
}
264+
91265
#[test]
92266
fn test_parse() {
93267
macro_rules! test_from_str {
@@ -107,8 +281,13 @@ mod tests {
107281

108282
test_from_str! {
109283
"local/build-fail" => Crate::Local("build-fail".to_string()),
284+
"path/pathtofile" => Crate::Path("pathtofile".to_string()),
285+
&format!("path/{}", utf8_percent_encode("path/with:stange?characters", &NON_ALPHANUMERIC)) => Crate::Path("path/with:stange?characters".to_string()),
110286
"gh/org/user" => Crate::GitHub(GitHubRepo{org: "org".to_string(), name: "user".to_string(), sha: None}),
111287
"gh/org/user/sha" => Crate::GitHub(GitHubRepo{org: "org".to_string(), name: "user".to_string(), sha: Some("sha".to_string())}),
288+
"git/url" => Crate::Git(GitRepo{url: "url".to_string(), sha: None}),
289+
&format!("git/{}", utf8_percent_encode("url/with:stange?characters", &NON_ALPHANUMERIC)) => Crate::Git(GitRepo{url: "url/with:stange?characters".to_string(), sha: None}),
290+
"git/url/sha" => Crate::Git(GitRepo{url: "url".to_string(), sha: Some("sha".to_string())}),
112291
"reg/name/version" => Crate::Registry(RegistryCrate{name: "name".to_string(), version: "version".to_string()}),
113292
}
114293
}

0 commit comments

Comments
 (0)