diff --git a/src/cargo/core/compiler/fingerprint/mod.rs b/src/cargo/core/compiler/fingerprint/mod.rs index aa8be50f7582..83ab0c82b4d3 100644 --- a/src/cargo/core/compiler/fingerprint/mod.rs +++ b/src/cargo/core/compiler/fingerprint/mod.rs @@ -1857,14 +1857,25 @@ where Err(..) => return Some(StaleItem::MissingFile(reference.to_path_buf())), }; + let skipable_dirs = if let Ok(cargo_home) = home::cargo_home() { + let skipable_dirs: Vec<_> = ["git", "registry"] + .into_iter() + .map(|subfolder| cargo_home.join(subfolder)) + .collect(); + Some(skipable_dirs) + } else { None }; + for path in paths { let path = path.as_ref(); - // Assuming anything in cargo_home is immutable (see also #9455 about marking it readonly) - // which avoids rebuilds when CI caches $CARGO_HOME/registry/{index, cache} and - // $CARGO_HOME/git/db across runs, keeping the content the same but changing the mtime. - if let Ok(true) = home::cargo_home().map(|home| path.starts_with(home)) { - continue; + // Assuming anything in cargo_home/{git, registry} is immutable + // (see also #9455 about marking the src directory readonly) which avoids rebuilds when CI + // caches $CARGO_HOME/registry/{index, cache} and $CARGO_HOME/git/db across runs, keeping + // the content the same but changing the mtime. + if let Some(ref skipable_dirs) = skipable_dirs { + if skipable_dirs.iter().any(|dir| path.starts_with(dir)) { + continue; + } } let path_mtime = match mtime_cache.entry(path.to_path_buf()) { Entry::Occupied(o) => *o.get(), diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index 8cb064a6f929..87280f80c70b 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -5972,6 +5972,56 @@ fn build_with_relative_cargo_home_path() { p.cargo("build").env("CARGO_HOME", "./cargo_home/").run(); } +#[cargo_test] +fn skip_mtime_check_in_selected_cargo_home_subdirs() { + // Run once without cache + let p = project() + .at("cargo_home/registry/foo") + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", r#"fn main() { println!("1"); }"#) + .build(); + let project_root = p.root(); + let cargo_home = project_root + .parent().unwrap() + .parent().unwrap() + .to_str().unwrap(); + p.cargo("run") + .env("CARGO_HOME", &cargo_home) + .with_stdout("1") + .run(); + // Run with cache + p.change_file("src/main.rs", r#"fn main() { println!("2"); }"#); + p.cargo("run") + .env("CARGO_HOME", &cargo_home) + .with_stdout("1") + .run(); +} + +#[cargo_test] +fn use_mtime_cache_in_cargo_home() { + println!("Without cache"); + let p = project() + .at("cargo_home/foo") + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", r#"fn main() { println!("1"); }"#) + .build(); + let project_root = p.root(); + let cargo_home = project_root + .parent().unwrap() + .parent().unwrap() + .to_str().unwrap(); + p.cargo("run") + .env("CARGO_HOME", &cargo_home) + .with_stdout("1") + .run(); + println!("With cache"); + p.change_file("src/main.rs", r#"fn main() { println!("2"); }"#); + p.cargo("run") + .env("CARGO_HOME", &cargo_home) + .with_stdout("2") + .run(); +} + #[cargo_test] fn user_specific_cfgs_are_filtered_out() { let p = project()