187187//! See the `A-rebuild-detection` flag on the issue tracker for more:
188188//! <https://github.com/rust-lang/cargo/issues?q=is%3Aissue+is%3Aopen+label%3AA-rebuild-detection>
189189
190- use std:: collections:: HashMap ;
190+ use std:: collections:: hash_map :: { Entry , HashMap } ;
191191use std:: env;
192192use std:: fs;
193193use std:: hash:: { self , Hasher } ;
@@ -539,6 +539,7 @@ impl LocalFingerprint {
539539 /// file accesses.
540540 fn find_stale_file (
541541 & self ,
542+ mtime_cache : & mut HashMap < PathBuf , FileTime > ,
542543 pkg_root : & Path ,
543544 target_root : & Path ,
544545 ) -> CargoResult < Option < StaleFile > > {
@@ -550,7 +551,7 @@ impl LocalFingerprint {
550551 LocalFingerprint :: CheckDepInfo { dep_info } => {
551552 let dep_info = target_root. join ( dep_info) ;
552553 if let Some ( paths) = parse_dep_info ( pkg_root, target_root, & dep_info) ? {
553- Ok ( find_stale_file ( & dep_info, paths. iter ( ) ) )
554+ Ok ( find_stale_file ( mtime_cache , & dep_info, paths. iter ( ) ) )
554555 } else {
555556 Ok ( Some ( StaleFile :: Missing ( dep_info) ) )
556557 }
@@ -559,6 +560,7 @@ impl LocalFingerprint {
559560 // We need to verify that no paths listed in `paths` are newer than
560561 // the `output` path itself, or the last time the build script ran.
561562 LocalFingerprint :: RerunIfChanged { output, paths } => Ok ( find_stale_file (
563+ mtime_cache,
562564 & target_root. join ( output) ,
563565 paths. iter ( ) . map ( |p| pkg_root. join ( p) ) ,
564566 ) ) ,
@@ -756,7 +758,12 @@ impl Fingerprint {
756758 /// dependencies up to this unit as well. This function assumes that the
757759 /// unit starts out as `FsStatus::Stale` and then it will optionally switch
758760 /// it to `UpToDate` if it can.
759- fn check_filesystem ( & mut self , pkg_root : & Path , target_root : & Path ) -> CargoResult < ( ) > {
761+ fn check_filesystem (
762+ & mut self ,
763+ mtime_cache : & mut HashMap < PathBuf , FileTime > ,
764+ pkg_root : & Path ,
765+ target_root : & Path ,
766+ ) -> CargoResult < ( ) > {
760767 assert ! ( !self . fs_status. up_to_date( ) ) ;
761768
762769 let mut mtimes = HashMap :: new ( ) ;
@@ -840,7 +847,7 @@ impl Fingerprint {
840847 // files for this package itself. If we do find something log a helpful
841848 // message and bail out so we stay stale.
842849 for local in self . local . get_mut ( ) . unwrap ( ) . iter ( ) {
843- if let Some ( file) = local. find_stale_file ( pkg_root, target_root) ? {
850+ if let Some ( file) = local. find_stale_file ( mtime_cache , pkg_root, target_root) ? {
844851 file. log ( ) ;
845852 return Ok ( ( ) ) ;
846853 }
@@ -1015,7 +1022,7 @@ fn calculate<'a, 'cfg>(
10151022 // After we built the initial `Fingerprint` be sure to update the
10161023 // `fs_status` field of it.
10171024 let target_root = target_root ( cx) ;
1018- fingerprint. check_filesystem ( unit. pkg . root ( ) , & target_root) ?;
1025+ fingerprint. check_filesystem ( & mut cx . mtime_cache , unit. pkg . root ( ) , & target_root) ?;
10191026
10201027 let fingerprint = Arc :: new ( fingerprint) ;
10211028 cx. fingerprints . insert ( * unit, Arc :: clone ( & fingerprint) ) ;
@@ -1098,13 +1105,10 @@ fn calculate_normal<'a, 'cfg>(
10981105 } )
10991106}
11001107
1101- // We want to use the mtime for files if we're a path source, but if we're a
1102- // git/registry source, then the mtime of files may fluctuate, but they won't
1103- // change so long as the source itself remains constant (which is the
1104- // responsibility of the source)
1108+ /// Whether or not the fingerprint should track the dependencies from the
1109+ /// dep-info file for this unit.
11051110fn use_dep_info ( unit : & Unit < ' _ > ) -> bool {
1106- let path = unit. pkg . summary ( ) . source_id ( ) . is_path ( ) ;
1107- !unit. mode . is_doc ( ) && path
1111+ !unit. mode . is_doc ( )
11081112}
11091113
11101114/// Calculate a fingerprint for an "execute a build script" unit. This is an
@@ -1422,11 +1426,7 @@ pub fn parse_dep_info(
14221426 }
14231427 } )
14241428 . collect :: < Result < Vec < _ > , _ > > ( ) ?;
1425- if paths. is_empty ( ) {
1426- Ok ( None )
1427- } else {
1428- Ok ( Some ( paths) )
1429- }
1429+ Ok ( Some ( paths) )
14301430}
14311431
14321432fn pkg_fingerprint ( bcx : & BuildContext < ' _ , ' _ > , pkg : & Package ) -> CargoResult < String > {
@@ -1439,7 +1439,11 @@ fn pkg_fingerprint(bcx: &BuildContext<'_, '_>, pkg: &Package) -> CargoResult<Str
14391439 source. fingerprint ( pkg)
14401440}
14411441
1442- fn find_stale_file < I > ( reference : & Path , paths : I ) -> Option < StaleFile >
1442+ fn find_stale_file < I > (
1443+ mtime_cache : & mut HashMap < PathBuf , FileTime > ,
1444+ reference : & Path ,
1445+ paths : I ,
1446+ ) -> Option < StaleFile >
14431447where
14441448 I : IntoIterator ,
14451449 I :: Item : AsRef < Path > ,
@@ -1451,9 +1455,15 @@ where
14511455
14521456 for path in paths {
14531457 let path = path. as_ref ( ) ;
1454- let path_mtime = match paths:: mtime ( path) {
1455- Ok ( mtime) => mtime,
1456- Err ( ..) => return Some ( StaleFile :: Missing ( path. to_path_buf ( ) ) ) ,
1458+ let path_mtime = match mtime_cache. entry ( path. to_path_buf ( ) ) {
1459+ Entry :: Occupied ( o) => * o. get ( ) ,
1460+ Entry :: Vacant ( v) => {
1461+ let mtime = match paths:: mtime ( path) {
1462+ Ok ( mtime) => mtime,
1463+ Err ( ..) => return Some ( StaleFile :: Missing ( path. to_path_buf ( ) ) ) ,
1464+ } ;
1465+ * v. insert ( mtime)
1466+ }
14571467 } ;
14581468
14591469 // TODO: fix #5918.
@@ -1540,6 +1550,9 @@ impl DepInfoPathType {
15401550/// The `rustc_cwd` argument is the absolute path to the cwd of the compiler
15411551/// when it was invoked.
15421552///
1553+ /// If the `allow_package` argument is false, then package-relative paths are
1554+ /// skipped and ignored.
1555+ ///
15431556/// The serialized Cargo format will contain a list of files, all of which are
15441557/// relative if they're under `root`. or absolute if they're elsewhere.
15451558pub fn translate_dep_info (
@@ -1548,6 +1561,7 @@ pub fn translate_dep_info(
15481561 rustc_cwd : & Path ,
15491562 pkg_root : & Path ,
15501563 target_root : & Path ,
1564+ allow_package : bool ,
15511565) -> CargoResult < ( ) > {
15521566 let target = parse_rustc_dep_info ( rustc_dep_info) ?;
15531567 let deps = & target
@@ -1561,6 +1575,9 @@ pub fn translate_dep_info(
15611575 let ( ty, path) = if let Ok ( stripped) = file. strip_prefix ( target_root) {
15621576 ( DepInfoPathType :: TargetRootRelative , stripped)
15631577 } else if let Ok ( stripped) = file. strip_prefix ( pkg_root) {
1578+ if !allow_package {
1579+ continue ;
1580+ }
15641581 ( DepInfoPathType :: PackageRootRelative , stripped)
15651582 } else {
15661583 // It's definitely not target root relative, but this is an absolute path (since it was
0 commit comments