@@ -10,7 +10,7 @@ use std::io::IsTerminal;
1010use std:: path:: { Path , PathBuf , absolute} ;
1111use std:: process:: Command ;
1212use std:: str:: FromStr ;
13- use std:: sync:: OnceLock ;
13+ use std:: sync:: { Arc , Mutex , OnceLock } ;
1414use std:: { cmp, env, fs} ;
1515
1616use build_helper:: ci:: CiEnv ;
@@ -421,6 +421,9 @@ pub struct Config {
421421 pub compiletest_use_stage0_libtest : bool ,
422422
423423 pub is_running_on_ci : bool ,
424+
425+ /// Cache for determining path modifications
426+ pub path_modification_cache : Arc < Mutex < HashMap < Vec < & ' static str > , PathFreshness > > > ,
424427}
425428
426429#[ derive( Clone , Debug , Default ) ]
@@ -3184,17 +3187,34 @@ impl Config {
31843187 }
31853188
31863189 /// Returns true if any of the `paths` have been modified locally.
3187- pub fn has_changes_from_upstream ( & self , paths : & [ & str ] ) -> bool {
3190+ pub fn has_changes_from_upstream ( & self , paths : & [ & ' static str ] ) -> bool {
31883191 match self . check_path_modifications ( paths) {
31893192 PathFreshness :: LastModifiedUpstream { .. } => false ,
31903193 PathFreshness :: HasLocalModifications { .. } | PathFreshness :: MissingUpstream => true ,
31913194 }
31923195 }
31933196
31943197 /// Checks whether any of the given paths have been modified w.r.t. upstream.
3195- pub fn check_path_modifications ( & self , paths : & [ & str ] ) -> PathFreshness {
3196- check_path_modifications ( Some ( & self . src ) , & self . git_config ( ) , paths, CiEnv :: current ( ) )
3198+ pub fn check_path_modifications ( & self , paths : & [ & ' static str ] ) -> PathFreshness {
3199+ // Checking path modifications through git can be relatively expensive (>100ms).
3200+ // We do not assume that the sources would change during bootstrap's execution,
3201+ // so we can cache the results here.
3202+ // Note that we do not use a static variable for the cache, because it would cause problems
3203+ // in tests that create separate `Config` instsances.
3204+ self . path_modification_cache
3205+ . lock ( )
31973206 . unwrap ( )
3207+ . entry ( paths. to_vec ( ) )
3208+ . or_insert_with ( || {
3209+ check_path_modifications (
3210+ Some ( & self . src ) ,
3211+ & self . git_config ( ) ,
3212+ paths,
3213+ CiEnv :: current ( ) ,
3214+ )
3215+ . unwrap ( )
3216+ } )
3217+ . clone ( )
31983218 }
31993219
32003220 pub fn ci_env ( & self ) -> CiEnv {
0 commit comments