Repository: rust-analyzer/rust-analyzer
Pull request #5790 (2020-08-18 08:40:39)

Revive cache cleaning

bors r+
🤖

matklad: bors r-
bors[bot]: Canceled.
matklad: bors r+
bors[bot]: Build failed:
  * [Rust (windows-latest)](https://github.com/rust-analyzer/rust-analyzer/runs/997468914)

Patch:
diff --git a/crates/rust-analyzer/tests/heavy_tests/support.rs b/crates/rust-analyzer/tests/rust-analyzer/support.rs
similarity index 100%
rename from crates/rust-analyzer/tests/heavy_tests/support.rs
rename to crates/rust-analyzer/tests/rust-analyzer/support.rs
diff --git a/crates/rust-analyzer/tests/heavy_tests/testdir.rs b/crates/rust-analyzer/tests/rust-analyzer/testdir.rs
similarity index 100%
rename from crates/rust-analyzer/tests/heavy_tests/testdir.rs
rename to crates/rust-analyzer/tests/rust-analyzer/testdir.rs
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs
index f3ad81ba72..e790d995fb 100644
--- a/xtask/src/lib.rs
+++ b/xtask/src/lib.rs
@@ -3,14 +3,15 @@
 //! See https://github.com/matklad/cargo-xtask/
 
 pub mod not_bash;
+pub mod codegen;
+mod ast_src;
+
 pub mod install;
 pub mod release;
 pub mod dist;
 pub mod pre_commit;
 pub mod metrics;
-
-pub mod codegen;
-mod ast_src;
+pub mod pre_cache;
 
 use std::{
     env,
@@ -21,7 +22,7 @@ use walkdir::{DirEntry, WalkDir};
 
 use crate::{
     codegen::Mode,
-    not_bash::{fs2, pushd, pushenv, rm_rf},
+    not_bash::{pushd, pushenv},
 };
 
 pub use anyhow::{bail, Context as _, Result};
@@ -108,42 +109,6 @@ pub fn run_fuzzer() -> Result<()> {
     Ok(())
 }
 
-/// Cleans the `./target` dir after the build such that only
-/// dependencies are cached on CI.
-pub fn run_pre_cache() -> Result<()> {
-    let slow_tests_cookie = Path::new("./target/.slow_tests_cookie");
-    if !slow_tests_cookie.exists() {
-        panic!("slow tests were skipped on CI!")
-    }
-    rm_rf(slow_tests_cookie)?;
-
-    for entry in Path::new("./target/debug").read_dir()? {
-        let entry = entry?;
-        if entry.file_type().map(|it| it.is_file()).ok() == Some(true) {
-            // Can't delete yourself on windows :-(
-            if !entry.path().ends_with("xtask.exe") {
-                rm_rf(&entry.path())?
-            }
-        }
-    }
-
-    fs2::remove_file("./target/.rustc_info.json")?;
-    let to_delete = ["hir", "heavy_test", "xtask", "ide", "rust-analyzer"];
-    for &dir in ["./target/debug/deps", "target/debug/.fingerprint"].iter() {
-        for entry in Path::new(dir).read_dir()? {
-            let entry = entry?;
-            if to_delete.iter().any(|&it| entry.path().display().to_string().contains(it)) {
-                // Can't delete yourself on windows :-(
-                if !entry.path().ends_with("xtask.exe") {
-                    rm_rf(&entry.path())?
-                }
-            }
-        }
-    }
-
-    Ok(())
-}
-
 fn is_release_tag(tag: &str) -> bool {
     tag.len() == "2020-02-24".len() && tag.starts_with(|c: char| c.is_ascii_digit())
 }
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index b69b884e54..fb38fdc92f 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -17,9 +17,10 @@ use xtask::{
     install::{ClientOpt, InstallCmd, Malloc, ServerOpt},
     metrics::MetricsCmd,
     not_bash::pushd,
+    pre_cache::PreCacheCmd,
     pre_commit, project_root,
     release::{PromoteCmd, ReleaseCmd},
-    run_clippy, run_fuzzer, run_pre_cache, run_rustfmt, Result,
+    run_clippy, run_fuzzer, run_rustfmt, Result,
 };
 
 fn main() -> Result<()> {
@@ -100,7 +101,7 @@ FLAGS:
         }
         "pre-cache" => {
             args.finish()?;
-            run_pre_cache()
+            PreCacheCmd.run()
         }
         "release" => {
             let dry_run = args.contains("--dry-run");
diff --git a/xtask/src/pre_cache.rs b/xtask/src/pre_cache.rs
new file mode 100644
index 0000000000..47ba6ba246
--- /dev/null
+++ b/xtask/src/pre_cache.rs
@@ -0,0 +1,80 @@
+use std::{
+    fs::FileType,
+    path::{Path, PathBuf},
+};
+
+use anyhow::Result;
+
+use crate::not_bash::{fs2, rm_rf};
+
+pub struct PreCacheCmd;
+
+impl PreCacheCmd {
+    /// Cleans the `./target` dir after the build such that only
+    /// dependencies are cached on CI.
+    pub fn run(self) -> Result<()> {
+        let slow_tests_cookie = Path::new("./target/.slow_tests_cookie");
+        if !slow_tests_cookie.exists() {
+            panic!("slow tests were skipped on CI!")
+        }
+        rm_rf(slow_tests_cookie)?;
+
+        for path in read_dir("./target/debug", FileType::is_file)? {
+            // Can't delete yourself on windows :-(
+            if !path.ends_with("xtask.exe") {
+                rm_rf(&path)?
+            }
+        }
+
+        fs2::remove_file("./target/.rustc_info.json")?;
+
+        let to_delete = read_dir("./crates", FileType::is_dir)?
+            .into_iter()
+            .map(|path| path.file_name().unwrap().to_string_lossy().replace('-', "_"))
+            .collect::<Vec<_>>();
+
+        for &dir in ["./target/debug/deps", "target/debug/.fingerprint"].iter() {
+            for path in read_dir(dir, |_file_type| true)? {
+                if path.ends_with("xtask.exe") {
+                    continue;
+                }
+                let file_name = path.file_name().unwrap().to_string_lossy();
+                let (stem, _) = match rsplit_once(&file_name, '-') {
+                    Some(it) => it,
+                    None => {
+                        rm_rf(path)?;
+                        continue;
+                    }
+                };
+                let stem = stem.replace('-', "_");
+                if to_delete.contains(&stem) {
+                    rm_rf(path)?;
+                }
+            }
+        }
+
+        Ok(())
+    }
+}
+fn read_dir(path: impl AsRef<Path>, cond: impl Fn(&FileType) -> bool) -> Result<Vec<PathBuf>> {
+    read_dir_impl(path.as_ref(), &cond)
+}
+
+fn read_dir_impl(path: &Path, cond: &dyn Fn(&FileType) -> bool) -> Result<Vec<PathBuf>> {
+    let mut res = Vec::new();
+    for entry in path.read_dir()? {
+        let entry = entry?;
+        let file_type = entry.file_type()?;
+        if cond(&file_type) {
+            res.push(entry.path())
+        }
+    }
+    Ok(res)
+}
+
+fn rsplit_once(haystack: &str, delim: char) -> Option<(&str, &str)> {
+    let mut split = haystack.rsplitn(2, delim);
+    let suffix = split.next()?;
+    let prefix = split.next()?;
+    Some((prefix, suffix))
+}


Test patch:
diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/rust-analyzer/main.rs
similarity index 97%
rename from crates/rust-analyzer/tests/heavy_tests/main.rs
rename to crates/rust-analyzer/tests/rust-analyzer/main.rs
index 7370505f8b..fa315ff8ee 100644
--- a/crates/rust-analyzer/tests/heavy_tests/main.rs
+++ b/crates/rust-analyzer/tests/rust-analyzer/main.rs
@@ -1,3 +1,13 @@
+//! The most high-level integrated tests for rust-analyzer.
+//!
+//! This tests run a full LSP event loop, spawn cargo and process stdlib from
+//! sysroot. For this reason, the tests here are very slow, and should be
+//! avoided unless absolutely necessary.
+//!
+//! In particular, it's fine *not* to test that client & server agree on
+//! specific JSON shapes here -- there's little value in such tests, as we can't
+//! be sure without a real client anyway.
+
 mod testdir;
 mod support;