]> git.lizzy.rs Git - rust.git/blob - clippy_dev/src/bless.rs
Move/rename `lazy::Sync{OnceCell,Lazy}` to `sync::{Once,Lazy}Lock`
[rust.git] / clippy_dev / src / bless.rs
1 //! `bless` updates the reference files in the repo with changed output files
2 //! from the last test run.
3
4 use crate::cargo_clippy_path;
5 use std::ffi::OsStr;
6 use std::fs;
7 use std::path::{Path, PathBuf};
8 use std::sync::LazyLock;
9 use walkdir::{DirEntry, WalkDir};
10
11 static CLIPPY_BUILD_TIME: LazyLock<Option<std::time::SystemTime>> =
12     LazyLock::new(|| cargo_clippy_path().metadata().ok()?.modified().ok());
13
14 /// # Panics
15 ///
16 /// Panics if the path to a test file is broken
17 pub fn bless(ignore_timestamp: bool) {
18     let extensions = ["stdout", "stderr", "fixed"].map(OsStr::new);
19
20     WalkDir::new(build_dir())
21         .into_iter()
22         .map(Result::unwrap)
23         .filter(|entry| entry.path().extension().map_or(false, |ext| extensions.contains(&ext)))
24         .for_each(|entry| update_reference_file(&entry, ignore_timestamp));
25 }
26
27 fn update_reference_file(test_output_entry: &DirEntry, ignore_timestamp: bool) {
28     let test_output_path = test_output_entry.path();
29
30     let reference_file_name = test_output_entry.file_name().to_str().unwrap().replace(".stage-id", "");
31     let reference_file_path = Path::new("tests")
32         .join(test_output_path.strip_prefix(build_dir()).unwrap())
33         .with_file_name(reference_file_name);
34
35     // If the test output was not updated since the last clippy build, it may be outdated
36     if !ignore_timestamp && !updated_since_clippy_build(test_output_entry).unwrap_or(true) {
37         return;
38     }
39
40     let test_output_file = fs::read(&test_output_path).expect("Unable to read test output file");
41     let reference_file = fs::read(&reference_file_path).unwrap_or_default();
42
43     if test_output_file != reference_file {
44         // If a test run caused an output file to change, update the reference file
45         println!("updating {}", reference_file_path.display());
46         fs::copy(test_output_path, &reference_file_path).expect("Could not update reference file");
47     }
48 }
49
50 fn updated_since_clippy_build(entry: &DirEntry) -> Option<bool> {
51     let clippy_build_time = (*CLIPPY_BUILD_TIME)?;
52     let modified = entry.metadata().ok()?.modified().ok()?;
53     Some(modified >= clippy_build_time)
54 }
55
56 fn build_dir() -> PathBuf {
57     let mut path = std::env::current_exe().unwrap();
58     path.set_file_name("test");
59     path
60 }