Skip to content

Commit e39d131

Browse files
committed
Auto merge of #391 - ecstatic-morse:clippy-mode, r=pietroalbini
Add a new `clippy` mode to crater to test lint regressions Resolves #388. This adds a new mode, `clippy`, to crater which runs clippy on crates (duh :). I had to add some new options to minicrater, as well as change the invocation of `docker create`. See the commit messages for more info. This is still a work in progress as I'd like to add some documentation for the feature, but should be enough for a meaningful review.
2 parents 2c96710 + 42174eb commit e39d131

File tree

16 files changed

+202
-42
lines changed

16 files changed

+202
-42
lines changed

local-crates/clippy-warn/Cargo.toml

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "clippy-warn"
3+
version = "0.1.0"
4+
authors = ["Dylan MacKenzie <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]

local-crates/clippy-warn/src/main.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn main() {
2+
// Trigger `clippy::print_with_newline`
3+
print!("Hello, world!\n");
4+
}

src/dirs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@ pub(crate) fn crate_source_dir(ex: &Experiment, tc: &Toolchain, krate: &Crate) -
4343
EXPERIMENT_DIR
4444
.join(&ex.name)
4545
.join("sources")
46-
.join(tc.to_string())
46+
.join(tc.to_path_component())
4747
.join(krate.id())
4848
}

src/experiments.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ string_enum!(pub enum Mode {
2222
BuildAndTest => "build-and-test",
2323
BuildOnly => "build-only",
2424
CheckOnly => "check-only",
25+
Clippy => "clippy",
2526
Rustdoc => "rustdoc",
2627
UnstableFeatures => "unstable-features",
2728
});

src/runner/graph.rs

+4
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,10 @@ pub(super) fn build_graph(ex: &Experiment, config: &Config) -> TasksGraph {
266266
tc: tc.clone(),
267267
quiet,
268268
},
269+
Mode::Clippy => TaskStep::Clippy {
270+
tc: tc.clone(),
271+
quiet,
272+
},
269273
Mode::Rustdoc => TaskStep::Rustdoc {
270274
tc: tc.clone(),
271275
quiet,

src/runner/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ mod unstable_features;
88
use crate::config::Config;
99
use crate::crates::Crate;
1010
use crate::docker::DockerEnv;
11-
use crate::experiments::Experiment;
11+
use crate::experiments::{Experiment, Mode};
1212
use crate::logs::LogStorage;
1313
use crate::prelude::*;
1414
use crate::results::{FailureReason, TestResult, WriteResults};
@@ -87,6 +87,9 @@ fn run_ex_inner<DB: WriteResults + Sync>(
8787
info!("preparing the execution...");
8888
for tc in &ex.toolchains {
8989
tc.prepare()?;
90+
if ex.mode == Mode::Clippy {
91+
tc.install_rustup_component("clippy")?;
92+
}
9093
}
9194

9295
info!("running tasks in {} threads...", threads_count);

src/runner/tasks.rs

+24-30
Original file line numberDiff line numberDiff line change
@@ -54,42 +54,30 @@ pub(super) enum TaskStep {
5454
BuildAndTest { tc: Toolchain, quiet: bool },
5555
BuildOnly { tc: Toolchain, quiet: bool },
5656
CheckOnly { tc: Toolchain, quiet: bool },
57+
Clippy { tc: Toolchain, quiet: bool },
5758
Rustdoc { tc: Toolchain, quiet: bool },
5859
UnstableFeatures { tc: Toolchain },
5960
}
6061

6162
impl fmt::Debug for TaskStep {
6263
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63-
match *self {
64-
TaskStep::Prepare => write!(f, "prepare")?,
65-
TaskStep::Cleanup => write!(f, "cleanup")?,
66-
TaskStep::BuildAndTest { ref tc, quiet } => {
67-
write!(f, "build and test {}", tc.to_string())?;
68-
if quiet {
69-
write!(f, " (quiet)")?;
70-
}
71-
}
72-
TaskStep::BuildOnly { ref tc, quiet } => {
73-
write!(f, "build {}", tc.to_string())?;
74-
if quiet {
75-
write!(f, " (quiet)")?;
76-
}
77-
}
78-
TaskStep::CheckOnly { ref tc, quiet } => {
79-
write!(f, "check {}", tc.to_string())?;
80-
if quiet {
81-
write!(f, " (quiet)")?;
82-
}
83-
}
84-
TaskStep::Rustdoc { ref tc, quiet } => {
85-
write!(f, "doc {}", tc.to_string())?;
86-
if quiet {
87-
write!(f, " (quiet)")?;
88-
}
89-
}
90-
TaskStep::UnstableFeatures { ref tc } => {
91-
write!(f, "find unstable features on {}", tc.to_string())?;
92-
}
64+
let (name, quiet, tc) = match *self {
65+
TaskStep::Prepare => ("prepare", false, None),
66+
TaskStep::Cleanup => ("cleanup", false, None),
67+
TaskStep::BuildAndTest { ref tc, quiet } => ("build and test", quiet, Some(tc)),
68+
TaskStep::BuildOnly { ref tc, quiet } => ("build", quiet, Some(tc)),
69+
TaskStep::CheckOnly { ref tc, quiet } => ("check", quiet, Some(tc)),
70+
TaskStep::Clippy { ref tc, quiet } => ("clippy", quiet, Some(tc)),
71+
TaskStep::Rustdoc { ref tc, quiet } => ("doc", quiet, Some(tc)),
72+
TaskStep::UnstableFeatures { ref tc } => ("find unstable features on", false, Some(tc)),
73+
};
74+
75+
write!(f, "{}", name)?;
76+
if let Some(tc) = tc {
77+
write!(f, " {}", tc.to_string())?;
78+
}
79+
if quiet {
80+
write!(f, " (quiet)")?;
9381
}
9482
Ok(())
9583
}
@@ -120,6 +108,7 @@ impl Task {
120108
TaskStep::BuildAndTest { ref tc, .. }
121109
| TaskStep::BuildOnly { ref tc, .. }
122110
| TaskStep::CheckOnly { ref tc, .. }
111+
| TaskStep::Clippy { ref tc, .. }
123112
| TaskStep::Rustdoc { ref tc, .. }
124113
| TaskStep::UnstableFeatures { ref tc } => {
125114
db.get_result(ex, tc, &self.krate).unwrap_or(None).is_none()
@@ -141,6 +130,7 @@ impl Task {
141130
TaskStep::BuildAndTest { ref tc, .. }
142131
| TaskStep::BuildOnly { ref tc, .. }
143132
| TaskStep::CheckOnly { ref tc, .. }
133+
| TaskStep::Clippy { ref tc, .. }
144134
| TaskStep::Rustdoc { ref tc, .. }
145135
| TaskStep::UnstableFeatures { ref tc } => {
146136
let log_storage = state
@@ -199,6 +189,10 @@ impl Task {
199189
let ctx = TaskCtx::new(config, db, ex, tc, &self.krate, docker_env, state, quiet);
200190
test::run_test("checking", &ctx, test::test_check_only)?;
201191
}
192+
TaskStep::Clippy { ref tc, quiet } => {
193+
let ctx = TaskCtx::new(config, db, ex, tc, &self.krate, docker_env, state, quiet);
194+
test::run_test("linting", &ctx, test::test_clippy_only)?;
195+
}
202196
TaskStep::Rustdoc { ref tc, quiet } => {
203197
let ctx = TaskCtx::new(config, db, ex, tc, &self.krate, docker_env, state, quiet);
204198
test::run_test("documenting", &ctx, test::test_rustdoc)?;

src/runner/test.rs

+15
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,21 @@ pub(super) fn test_check_only<DB: WriteResults>(
151151
}
152152
}
153153

154+
pub(super) fn test_clippy_only<DB: WriteResults>(
155+
ctx: &TaskCtx<DB>,
156+
source_path: &Path,
157+
) -> Fallible<TestResult> {
158+
if let Err(err) = run_cargo(
159+
ctx,
160+
source_path,
161+
&["clippy", "--frozen", "--all", "--all-targets"],
162+
) {
163+
Ok(TestResult::BuildFail(failure_reason(&err)))
164+
} else {
165+
Ok(TestResult::TestPass)
166+
}
167+
}
168+
154169
pub(super) fn test_rustdoc<DB: WriteResults>(
155170
ctx: &TaskCtx<DB>,
156171
source_path: &Path,

src/server/routes/ui/experiments.rs

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ impl ExperimentData {
3939
Mode::BuildAndTest => "cargo test",
4040
Mode::BuildOnly => "cargo build",
4141
Mode::CheckOnly => "cargo check",
42+
Mode::Clippy => "cargo clippy",
4243
Mode::Rustdoc => "cargo doc",
4344
Mode::UnstableFeatures => "unstable features",
4445
},

src/toolchain.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,27 @@ impl Toolchain {
7171
}
7272
}
7373

74+
pub fn install_rustup_component(&self, component: &str) -> Fallible<()> {
75+
let toolchain_name = &self.rustup_name();
76+
info!(
77+
"installing component {} for toolchain {}",
78+
component, toolchain_name
79+
);
80+
81+
utils::try_hard(|| {
82+
RunCommand::new(&RUSTUP)
83+
.args(&["component", "add", "--toolchain", toolchain_name, component])
84+
.run()
85+
.with_context(|_| {
86+
format!(
87+
"unable to install component {} for toolchain {} via rustup",
88+
component, toolchain_name,
89+
)
90+
})
91+
})?;
92+
Ok(())
93+
}
94+
7495
pub fn target_dir(&self, ex_name: &str) -> PathBuf {
7596
let mut dir = ex_target_dir(ex_name);
7697

@@ -80,7 +101,7 @@ impl Toolchain {
80101
dir = dir.join("shared");
81102
}
82103

83-
dir.join(self.to_string())
104+
dir.join(self.to_path_component())
84105
}
85106

86107
pub fn prep_offline_registry(&self) -> Fallible<()> {
@@ -100,6 +121,12 @@ impl Toolchain {
100121
// is ready
101122
Ok(())
102123
}
124+
125+
pub fn to_path_component(&self) -> String {
126+
use url::percent_encoding::utf8_percent_encode as encode;
127+
128+
encode(&self.to_string(), utils::fs::FILENAME_ENCODE_SET).to_string()
129+
}
103130
}
104131

105132
impl fmt::Display for Toolchain {

src/utils/fs.rs

+8
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,16 @@ use crate::prelude::*;
22
use crate::utils::try_hard_limit;
33
use std::fs;
44
use std::path::{Path, PathBuf};
5+
use url::percent_encoding::SIMPLE_ENCODE_SET;
56
use walkdir::{DirEntry, WalkDir};
67

8+
url::define_encode_set! {
9+
/// The set of characters which cannot be used in a [filename on Windows][windows].
10+
///
11+
/// [windows]: https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file#naming-conventions
12+
pub FILENAME_ENCODE_SET = [SIMPLE_ENCODE_SET] | { '<', '>', ':', '"', '/', '\\', '|', '?', '*' }
13+
}
14+
715
pub(crate) fn try_canonicalize<P: AsRef<Path>>(path: P) -> PathBuf {
816
fs::canonicalize(&path).unwrap_or_else(|_| path.as_ref().to_path_buf())
917
}

tests/minicrater/clippy/config.toml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[server]
2+
bot-acl = [
3+
"pietroalbini",
4+
]
5+
6+
[server.labels]
7+
remove = "^S-"
8+
experiment-queued = "S-waiting-on-crater"
9+
experiment-completed = "S-waiting-on-review"
10+
11+
[demo-crates]
12+
crates = []
13+
github-repos = []
14+
local-crates = ["build-pass", "clippy-warn"]
15+
16+
[sandbox]
17+
memory-limit = "512M"
18+
build-log-max-size = "2M"
19+
build-log-max-lines = 1000
20+
21+
[crates]
22+
23+
[github-repos]
24+
25+
[local-crates]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"crates": [
3+
{
4+
"name": "build-pass (local)",
5+
"res": "test-pass",
6+
"runs": [
7+
{
8+
"log": "stable/local/build-pass",
9+
"res": "test-pass"
10+
},
11+
{
12+
"log": "stable%2Brustflags=-Dclippy::all/local/build-pass",
13+
"res": "test-pass"
14+
}
15+
],
16+
"url": "https://github.com/rust-lang-nursery/crater/tree/master/local-crates/build-pass"
17+
},
18+
{
19+
"name": "clippy-warn (local)",
20+
"res": "regressed",
21+
"runs": [
22+
{
23+
"log": "stable/local/clippy-warn",
24+
"res": "test-pass"
25+
},
26+
{
27+
"log": "stable%2Brustflags=-Dclippy::all/local/clippy-warn",
28+
"res": "build-fail:unknown"
29+
}
30+
],
31+
"url": "https://github.com/rust-lang-nursery/crater/tree/master/local-crates/clippy-warn"
32+
}
33+
]
34+
}

tests/minicrater/driver.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,21 @@ pub(super) struct MinicraterRun {
2626
pub(super) crate_select: &'static str,
2727
pub(super) multithread: bool,
2828
pub(super) ignore_blacklist: bool,
29+
pub(super) mode: &'static str,
30+
pub(super) toolchains: &'static [&'static str],
31+
}
32+
33+
impl Default for MinicraterRun {
34+
fn default() -> Self {
35+
MinicraterRun {
36+
ex: "default",
37+
crate_select: "demo",
38+
multithread: false,
39+
ignore_blacklist: false,
40+
mode: "build-and-test",
41+
toolchains: &["stable", "beta"],
42+
}
43+
}
2944
}
3045

3146
impl MinicraterRun {
@@ -54,8 +69,10 @@ impl MinicraterRun {
5469
.minicrater_exec();
5570

5671
// Define the experiment
72+
let mode = format!("--mode={}", self.mode);
5773
let crate_select = format!("--crate-select={}", self.crate_select);
58-
let mut define_args = vec!["define-ex", &ex_arg, "stable", "beta", &crate_select];
74+
let mut define_args = vec!["define-ex", &ex_arg, &crate_select, &mode];
75+
define_args.extend(self.toolchains);
5976
if self.ignore_blacklist {
6077
define_args.push("--ignore-blacklist");
6178
}

tests/minicrater/full/results.expected.json

+15
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,21 @@
7575
],
7676
"url": "https://github.com/rust-lang-nursery/crater/tree/master/local-crates/build-pass"
7777
},
78+
{
79+
"name": "clippy-warn (local)",
80+
"res": "test-pass",
81+
"runs": [
82+
{
83+
"log": "stable/local/clippy-warn",
84+
"res": "test-pass"
85+
},
86+
{
87+
"log": "beta/local/clippy-warn",
88+
"res": "test-pass"
89+
}
90+
],
91+
"url": "https://github.com/rust-lang-nursery/crater/tree/master/local-crates/clippy-warn"
92+
},
7893
{
7994
"name": "memory-hungry (local)",
8095
"res": "spurious-fixed",

0 commit comments

Comments
 (0)