about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Macleod <alex@macleod.io>2022-03-29 18:36:38 +0100
committerAlex Macleod <alex@macleod.io>2022-03-29 19:03:36 +0100
commit9a02386fd8f95303c4319bb3a18f8777e7908bcb (patch)
tree53241afdae66217829c02c0e88625754e7c1ae96
parent6206086dd5a83477131094b1f0ef61b10e7ced42 (diff)
downloadrust-9a02386fd8f95303c4319bb3a18f8777e7908bcb.tar.gz
rust-9a02386fd8f95303c4319bb3a18f8777e7908bcb.zip
Allow running `cargo dev lint` on a package directory
-rw-r--r--clippy_dev/Cargo.toml1
-rw-r--r--clippy_dev/src/bless.rs13
-rw-r--r--clippy_dev/src/lib.rs13
-rw-r--r--clippy_dev/src/lint.rs63
-rw-r--r--clippy_dev/src/main.rs20
5 files changed, 80 insertions, 30 deletions
diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml
index d133e8cddab..449ab1e9c7a 100644
--- a/clippy_dev/Cargo.toml
+++ b/clippy_dev/Cargo.toml
@@ -11,6 +11,7 @@ itertools = "0.10.1"
 opener = "0.5"
 regex = "1.5"
 shell-escape = "0.1"
+tempfile = "3.3"
 walkdir = "2.3"
 cargo_metadata = "0.14"
 
diff --git a/clippy_dev/src/bless.rs b/clippy_dev/src/bless.rs
index b0fb39e8169..8e5c739afe0 100644
--- a/clippy_dev/src/bless.rs
+++ b/clippy_dev/src/bless.rs
@@ -1,22 +1,15 @@
 //! `bless` updates the reference files in the repo with changed output files
 //! from the last test run.
 
+use crate::cargo_clippy_path;
 use std::ffi::OsStr;
 use std::fs;
 use std::lazy::SyncLazy;
 use std::path::{Path, PathBuf};
 use walkdir::{DirEntry, WalkDir};
 
-#[cfg(not(windows))]
-static CARGO_CLIPPY_EXE: &str = "cargo-clippy";
-#[cfg(windows)]
-static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe";
-
-static CLIPPY_BUILD_TIME: SyncLazy<Option<std::time::SystemTime>> = SyncLazy::new(|| {
-    let mut path = std::env::current_exe().unwrap();
-    path.set_file_name(CARGO_CLIPPY_EXE);
-    fs::metadata(path).ok()?.modified().ok()
-});
+static CLIPPY_BUILD_TIME: SyncLazy<Option<std::time::SystemTime>> =
+    SyncLazy::new(|| cargo_clippy_path().metadata().ok()?.modified().ok());
 
 /// # Panics
 ///
diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs
index 59fde447547..72d01db2738 100644
--- a/clippy_dev/src/lib.rs
+++ b/clippy_dev/src/lib.rs
@@ -13,6 +13,19 @@ pub mod serve;
 pub mod setup;
 pub mod update_lints;
 
+#[cfg(not(windows))]
+static CARGO_CLIPPY_EXE: &str = "cargo-clippy";
+#[cfg(windows)]
+static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe";
+
+/// Returns the path to the `cargo-clippy` binary
+#[must_use]
+pub fn cargo_clippy_path() -> PathBuf {
+    let mut path = std::env::current_exe().expect("failed to get current executable name");
+    path.set_file_name(CARGO_CLIPPY_EXE);
+    path
+}
+
 /// Returns the path to the Clippy project directory
 ///
 /// # Panics
diff --git a/clippy_dev/src/lint.rs b/clippy_dev/src/lint.rs
index b8287980a4b..1bc1a39542d 100644
--- a/clippy_dev/src/lint.rs
+++ b/clippy_dev/src/lint.rs
@@ -1,19 +1,52 @@
-use std::process::{self, Command};
+use crate::cargo_clippy_path;
+use std::process::{self, Command, ExitStatus};
+use std::{fs, io};
 
-pub fn run(filename: &str) {
-    let code = Command::new("cargo")
-        .args(["run", "--bin", "clippy-driver", "--"])
-        .args(["-L", "./target/debug"])
-        .args(["-Z", "no-codegen"])
-        .args(["--edition", "2021"])
-        .arg(filename)
-        .status()
-        .expect("failed to run cargo")
-        .code();
-
-    if code.is_none() {
-        eprintln!("Killed by signal");
+fn exit_if_err(status: io::Result<ExitStatus>) {
+    match status.expect("failed to run command").code() {
+        Some(0) => {},
+        Some(n) => process::exit(n),
+        None => {
+            eprintln!("Killed by signal");
+            process::exit(1);
+        },
     }
+}
+
+pub fn run(path: &str) {
+    let is_file = match fs::metadata(path) {
+        Ok(metadata) => metadata.is_file(),
+        Err(e) => {
+            eprintln!("Failed to read {path}: {e:?}");
+            process::exit(1);
+        },
+    };
+
+    if is_file {
+        exit_if_err(
+            Command::new("cargo")
+                .args(["run", "--bin", "clippy-driver", "--"])
+                .args(["-L", "./target/debug"])
+                .args(["-Z", "no-codegen"])
+                .args(["--edition", "2021"])
+                .arg(path)
+                .status(),
+        );
+    } else {
+        exit_if_err(Command::new("cargo").arg("build").status());
 
-    process::exit(code.unwrap_or(1));
+        // Run in a tempdir as changes to clippy do not retrigger linting
+        let target = tempfile::Builder::new()
+            .prefix("clippy")
+            .tempdir()
+            .expect("failed to create tempdir");
+
+        let status = Command::new(cargo_clippy_path())
+            .current_dir(path)
+            .env("CARGO_TARGET_DIR", target.as_ref())
+            .status();
+
+        target.close().expect("failed to remove tempdir");
+        exit_if_err(status);
+    }
 }
diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs
index 30a241c8ba1..b1fe35a0243 100644
--- a/clippy_dev/src/main.rs
+++ b/clippy_dev/src/main.rs
@@ -4,6 +4,7 @@
 
 use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
 use clippy_dev::{bless, fmt, lint, new_lint, serve, setup, update_lints};
+use indoc::indoc;
 fn main() {
     let matches = get_clap_config();
 
@@ -56,8 +57,8 @@ fn main() {
             serve::run(port, lint);
         },
         ("lint", Some(matches)) => {
-            let filename = matches.value_of("filename").unwrap();
-            lint::run(filename);
+            let path = matches.value_of("path").unwrap();
+            lint::run(path);
         },
         _ => {},
     }
@@ -225,11 +226,20 @@ fn get_clap_config<'a>() -> ArgMatches<'a> {
         )
         .subcommand(
             SubCommand::with_name("lint")
-                .about("Manually run clippy on a file")
+                .about("Manually run clippy on a file or package")
+                .after_help(indoc! {"
+                    EXAMPLES
+                        Lint a single file:
+                            cargo dev lint tests/ui/attrs.rs
+
+                        Lint a package directory:
+                            cargo dev lint tests/ui-cargo/wildcard_dependencies/fail
+                            cargo dev lint ~/my-project
+                "})
                 .arg(
-                    Arg::with_name("filename")
+                    Arg::with_name("path")
                         .required(true)
-                        .help("The path to a file to lint"),
+                        .help("The path to a file or package directory to lint"),
                 ),
         )
         .get_matches()