@@ -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:: { LazyLock , Mutex , OnceLock } ;
1414use std:: { cmp, env, fs} ;
1515
1616use build_helper:: ci:: CiEnv ;
@@ -3130,17 +3130,34 @@ impl Config {
31303130 }
31313131
31323132 /// Returns true if any of the `paths` have been modified locally.
3133- pub fn has_changes_from_upstream ( & self , paths : & [ & str ] ) -> bool {
3133+ pub fn has_changes_from_upstream ( & self , paths : & [ & ' static str ] ) -> bool {
31343134 match self . check_path_modifications ( paths) {
31353135 PathFreshness :: LastModifiedUpstream { .. } => false ,
31363136 PathFreshness :: HasLocalModifications { .. } | PathFreshness :: MissingUpstream => true ,
31373137 }
31383138 }
31393139
31403140 /// Checks whether any of the given paths have been modified w.r.t. upstream.
3141- pub fn check_path_modifications ( & self , paths : & [ & str ] ) -> PathFreshness {
3142- check_path_modifications ( Some ( & self . src ) , & self . git_config ( ) , paths, CiEnv :: current ( ) )
3141+ pub fn check_path_modifications ( & self , paths : & [ & ' static str ] ) -> PathFreshness {
3142+ // Checking path modifications through git can be relatively expensive (>100ms).
3143+ // We do not assume that the sources would change during bootstrap's execution,
3144+ // so we can cache the results here.
3145+ static MODIFICATION_CACHE : LazyLock < Mutex < HashMap < Vec < & ' static str > , PathFreshness > > > =
3146+ LazyLock :: new ( || Mutex :: new ( Default :: default ( ) ) ) ;
3147+ MODIFICATION_CACHE
3148+ . lock ( )
31433149 . unwrap ( )
3150+ . entry ( paths. to_vec ( ) )
3151+ . or_insert_with ( || {
3152+ check_path_modifications (
3153+ Some ( & self . src ) ,
3154+ & self . git_config ( ) ,
3155+ paths,
3156+ CiEnv :: current ( ) ,
3157+ )
3158+ . unwrap ( )
3159+ } )
3160+ . clone ( )
31443161 }
31453162}
31463163
0 commit comments