@@ -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 ;
@@ -418,6 +418,9 @@ pub struct Config {
418418 pub compiletest_diff_tool : Option < String > ,
419419
420420 pub is_running_on_ci : bool ,
421+
422+ /// Cache for determining path modifications
423+ pub path_modification_cache : Arc < Mutex < HashMap < Vec < & ' static str > , PathFreshness > > > ,
421424}
422425
423426#[ derive( Clone , Debug , Default ) ]
@@ -3152,17 +3155,34 @@ impl Config {
31523155 }
31533156
31543157 /// Returns true if any of the `paths` have been modified locally.
3155- pub fn has_changes_from_upstream ( & self , paths : & [ & str ] ) -> bool {
3158+ pub fn has_changes_from_upstream ( & self , paths : & [ & ' static str ] ) -> bool {
31563159 match self . check_path_modifications ( paths) {
31573160 PathFreshness :: LastModifiedUpstream { .. } => false ,
31583161 PathFreshness :: HasLocalModifications { .. } | PathFreshness :: MissingUpstream => true ,
31593162 }
31603163 }
31613164
31623165 /// Checks whether any of the given paths have been modified w.r.t. upstream.
3163- pub fn check_path_modifications ( & self , paths : & [ & str ] ) -> PathFreshness {
3164- check_path_modifications ( Some ( & self . src ) , & self . git_config ( ) , paths, CiEnv :: current ( ) )
3166+ pub fn check_path_modifications ( & self , paths : & [ & ' static str ] ) -> PathFreshness {
3167+ // Checking path modifications through git can be relatively expensive (>100ms).
3168+ // We do not assume that the sources would change during bootstrap's execution,
3169+ // so we can cache the results here.
3170+ // Note that we do not use a static variable for the cache, because it would cause problems
3171+ // in tests that create separate `Config` instsances.
3172+ self . path_modification_cache
3173+ . lock ( )
31653174 . unwrap ( )
3175+ . entry ( paths. to_vec ( ) )
3176+ . or_insert_with ( || {
3177+ check_path_modifications (
3178+ Some ( & self . src ) ,
3179+ & self . git_config ( ) ,
3180+ paths,
3181+ CiEnv :: current ( ) ,
3182+ )
3183+ . unwrap ( )
3184+ } )
3185+ . clone ( )
31663186 }
31673187
31683188 pub fn ci_env ( & self ) -> CiEnv {
0 commit comments