1 //! `bless` updates the reference files in the repo with changed output files
2 //! from the last test run.
4 use crate::cargo_clippy_path;
7 use std::path::{Path, PathBuf};
8 use std::sync::LazyLock;
9 use walkdir::{DirEntry, WalkDir};
11 static CLIPPY_BUILD_TIME: LazyLock<Option<std::time::SystemTime>> =
12 LazyLock::new(|| cargo_clippy_path().metadata().ok()?.modified().ok());
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);
20 WalkDir::new(build_dir())
23 .filter(|entry| entry.path().extension().map_or(false, |ext| extensions.contains(&ext)))
24 .for_each(|entry| update_reference_file(&entry, ignore_timestamp));
27 fn update_reference_file(test_output_entry: &DirEntry, ignore_timestamp: bool) {
28 let test_output_path = test_output_entry.path();
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);
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) {
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();
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");
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)
56 fn build_dir() -> PathBuf {
57 let mut path = std::env::current_exe().unwrap();
58 path.set_file_name("test");