about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-08-16 00:20:31 +0000
committerbors <bors@rust-lang.org>2021-08-16 00:20:31 +0000
commitd4e2fcabb1cd69ecea19c6f8503ca86a34a183ec (patch)
tree03d240dc6939a239c7b5cac57c9417f641816fd6
parent5449e23e671c500458ba70f5890fc5caa2853845 (diff)
parent997ddbbfd8adf3a56307c817d562fc6d07bcbd6c (diff)
downloadrust-d4e2fcabb1cd69ecea19c6f8503ca86a34a183ec.tar.gz
rust-d4e2fcabb1cd69ecea19c6f8503ca86a34a183ec.zip
Auto merge of #7521 - rukai:fix_lintcheck_local_path_handling, r=camsteffen
lintcheck always copies in a fresh crate when provided with a crate path

changelog: none

When lintcheck is run on local crates it copies the crate to `target/lintcheck/sources/crate_name` on the first run only.
Then in subsequent runs of lintcheck it reuses this same copy.
This caching behaviour makes sense when dealing with immutable crates.io releases and git commits.
However it is quite surprising that the changes to my local crate are not used when I run lintcheck.

To fix this I removed the copy, instead clippy runs directly off the provided crate folder.
I have tested this and have not observed any negative effects from doing this.
But maybe i'm missing something as im not familiar with clippy!

Alternatively we could make it copy the entire crate every run, but that seems problematic to me as multi-gigabyte target folders will take a long time to copy and wear down SSDs for developers who frequently run lintcheck.
-rw-r--r--lintcheck/Cargo.toml1
-rw-r--r--lintcheck/src/main.rs46
2 files changed, 29 insertions, 18 deletions
diff --git a/lintcheck/Cargo.toml b/lintcheck/Cargo.toml
index 8c33fa372ec..ada033de6e3 100644
--- a/lintcheck/Cargo.toml
+++ b/lintcheck/Cargo.toml
@@ -19,6 +19,7 @@ serde_json = {version = "1.0"}
 tar = {version = "0.4.30"}
 toml = {version = "0.5"}
 ureq = {version = "2.0.0-rc3"}
+walkdir = {version = "2.3.2"}
 
 [features]
 deny-warnings = []
diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs
index 7d2f3173fb0..f1e03ba4296 100644
--- a/lintcheck/src/main.rs
+++ b/lintcheck/src/main.rs
@@ -21,6 +21,7 @@ use clap::{App, Arg, ArgMatches};
 use rayon::prelude::*;
 use serde::{Deserialize, Serialize};
 use serde_json::Value;
+use walkdir::{DirEntry, WalkDir};
 
 #[cfg(not(windows))]
 const CLIPPY_DRIVER_PATH: &str = "target/debug/clippy-driver";
@@ -193,32 +194,41 @@ impl CrateSource {
                 }
             },
             CrateSource::Path { name, path, options } => {
-                use fs_extra::dir;
-
-                // simply copy the entire directory into our target dir
-                let copy_dest = PathBuf::from(format!("{}/", LINTCHECK_SOURCES));
+                // copy path into the dest_crate_root but skip directories that contain a CACHEDIR.TAG file.
+                // The target/ directory contains a CACHEDIR.TAG file so it is the most commonly skipped directory
+                // as a result of this filter.
+                let dest_crate_root = PathBuf::from(LINTCHECK_SOURCES).join(name);
+                if dest_crate_root.exists() {
+                    println!("Deleting existing directory at {:?}", dest_crate_root);
+                    std::fs::remove_dir_all(&dest_crate_root).unwrap();
+                }
 
-                // the source path of the crate we copied,  ${copy_dest}/crate_name
-                let crate_root = copy_dest.join(name); // .../crates/local_crate
+                println!("Copying {:?} to {:?}", path, dest_crate_root);
 
-                if crate_root.exists() {
-                    println!(
-                        "Not copying {} to {}, destination already exists",
-                        path.display(),
-                        crate_root.display()
-                    );
-                } else {
-                    println!("Copying {} to {}", path.display(), copy_dest.display());
+                fn is_cache_dir(entry: &DirEntry) -> bool {
+                    std::fs::read(entry.path().join("CACHEDIR.TAG"))
+                        .map(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55"))
+                        .unwrap_or(false)
+                }
 
-                    dir::copy(path, &copy_dest, &dir::CopyOptions::new()).unwrap_or_else(|_| {
-                        panic!("Failed to copy from {}, to  {}", path.display(), crate_root.display())
-                    });
+                for entry in WalkDir::new(path).into_iter().filter_entry(|e| !is_cache_dir(e)) {
+                    let entry = entry.unwrap();
+                    let entry_path = entry.path();
+                    let relative_entry_path = entry_path.strip_prefix(path).unwrap();
+                    let dest_path = dest_crate_root.join(relative_entry_path);
+                    let metadata = entry_path.symlink_metadata().unwrap();
+
+                    if metadata.is_dir() {
+                        std::fs::create_dir(dest_path).unwrap();
+                    } else if metadata.is_file() {
+                        std::fs::copy(entry_path, dest_path).unwrap();
+                    }
                 }
 
                 Crate {
                     version: String::from("local"),
                     name: name.clone(),
-                    path: crate_root,
+                    path: dest_crate_root,
                     options: options.clone(),
                 }
             },