@@ -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 ) ]
@@ -3175,17 +3178,34 @@ impl Config {
31753178 }
31763179
31773180 /// Returns true if any of the `paths` have been modified locally.
3178- pub fn has_changes_from_upstream ( & self , paths : & [ & str ] ) -> bool {
3181+ pub fn has_changes_from_upstream ( & self , paths : & [ & ' static str ] ) -> bool {
31793182 match self . check_path_modifications ( paths) {
31803183 PathFreshness :: LastModifiedUpstream { .. } => false ,
31813184 PathFreshness :: HasLocalModifications { .. } | PathFreshness :: MissingUpstream => true ,
31823185 }
31833186 }
31843187
31853188 /// Checks whether any of the given paths have been modified w.r.t. upstream.
3186- pub fn check_path_modifications ( & self , paths : & [ & str ] ) -> PathFreshness {
3187- check_path_modifications ( Some ( & self . src ) , & self . git_config ( ) , paths, CiEnv :: current ( ) )
3189+ pub fn check_path_modifications ( & self , paths : & [ & ' static str ] ) -> PathFreshness {
3190+ // Checking path modifications through git can be relatively expensive (>100ms).
3191+ // We do not assume that the sources would change during bootstrap's execution,
3192+ // so we can cache the results here.
3193+ // Note that we do not use a static variable for the cache, because it would cause problems
3194+ // in tests that create separate `Config` instsances.
3195+ self . path_modification_cache
3196+ . lock ( )
31883197 . unwrap ( )
3198+ . entry ( paths. to_vec ( ) )
3199+ . or_insert_with ( || {
3200+ check_path_modifications (
3201+ Some ( & self . src ) ,
3202+ & self . git_config ( ) ,
3203+ paths,
3204+ CiEnv :: current ( ) ,
3205+ )
3206+ . unwrap ( )
3207+ } )
3208+ . clone ( )
31893209 }
31903210
31913211 pub fn ci_env ( & self ) -> CiEnv {
0 commit comments