@@ -11,7 +11,7 @@ use std::io::IsTerminal;
1111use std:: path:: { Path , PathBuf , absolute} ;
1212use std:: process:: Command ;
1313use std:: str:: FromStr ;
14- use std:: sync:: OnceLock ;
14+ use std:: sync:: { Arc , Mutex , OnceLock } ;
1515use std:: { cmp, env, fs} ;
1616
1717use build_helper:: ci:: CiEnv ;
@@ -422,6 +422,9 @@ pub struct Config {
422422 pub compiletest_use_stage0_libtest : bool ,
423423
424424 pub is_running_on_ci : bool ,
425+
426+ /// Cache for determining path modifications
427+ pub path_modification_cache : Arc < Mutex < HashMap < Vec < & ' static str > , PathFreshness > > > ,
425428}
426429
427430#[ derive( Clone , Debug , Default ) ]
@@ -3294,17 +3297,34 @@ impl Config {
32943297 }
32953298
32963299 /// Returns true if any of the `paths` have been modified locally.
3297- pub fn has_changes_from_upstream ( & self , paths : & [ & str ] ) -> bool {
3300+ pub fn has_changes_from_upstream ( & self , paths : & [ & ' static str ] ) -> bool {
32983301 match self . check_path_modifications ( paths) {
32993302 PathFreshness :: LastModifiedUpstream { .. } => false ,
33003303 PathFreshness :: HasLocalModifications { .. } | PathFreshness :: MissingUpstream => true ,
33013304 }
33023305 }
33033306
33043307 /// Checks whether any of the given paths have been modified w.r.t. upstream.
3305- pub fn check_path_modifications ( & self , paths : & [ & str ] ) -> PathFreshness {
3306- check_path_modifications ( Some ( & self . src ) , & self . git_config ( ) , paths, CiEnv :: current ( ) )
3308+ pub fn check_path_modifications ( & self , paths : & [ & ' static str ] ) -> PathFreshness {
3309+ // Checking path modifications through git can be relatively expensive (>100ms).
3310+ // We do not assume that the sources would change during bootstrap's execution,
3311+ // so we can cache the results here.
3312+ // Note that we do not use a static variable for the cache, because it would cause problems
3313+ // in tests that create separate `Config` instsances.
3314+ self . path_modification_cache
3315+ . lock ( )
33073316 . unwrap ( )
3317+ . entry ( paths. to_vec ( ) )
3318+ . or_insert_with ( || {
3319+ check_path_modifications (
3320+ Some ( & self . src ) ,
3321+ & self . git_config ( ) ,
3322+ paths,
3323+ CiEnv :: current ( ) ,
3324+ )
3325+ . unwrap ( )
3326+ } )
3327+ . clone ( )
33083328 }
33093329
33103330 /// Checks if the given target is the same as the host target.
0 commit comments