@@ -10,7 +10,7 @@ use std::io::IsTerminal;
10
10
use std:: path:: { Path , PathBuf , absolute} ;
11
11
use std:: process:: Command ;
12
12
use std:: str:: FromStr ;
13
- use std:: sync:: OnceLock ;
13
+ use std:: sync:: { Arc , Mutex , OnceLock } ;
14
14
use std:: { cmp, env, fs} ;
15
15
16
16
use build_helper:: ci:: CiEnv ;
@@ -415,6 +415,9 @@ pub struct Config {
415
415
416
416
/// Command for visual diff display, e.g. `diff-tool --color=always`.
417
417
pub compiletest_diff_tool : Option < String > ,
418
+
419
+ /// Cache for determining path modifications
420
+ pub path_modification_cache : Arc < Mutex < HashMap < Vec < & ' static str > , PathFreshness > > > ,
418
421
}
419
422
420
423
#[ derive( Clone , Debug , Default ) ]
@@ -3130,17 +3133,34 @@ impl Config {
3130
3133
}
3131
3134
3132
3135
/// Returns true if any of the `paths` have been modified locally.
3133
- pub fn has_changes_from_upstream ( & self , paths : & [ & str ] ) -> bool {
3136
+ pub fn has_changes_from_upstream ( & self , paths : & [ & ' static str ] ) -> bool {
3134
3137
match self . check_path_modifications ( paths) {
3135
3138
PathFreshness :: LastModifiedUpstream { .. } => false ,
3136
3139
PathFreshness :: HasLocalModifications { .. } | PathFreshness :: MissingUpstream => true ,
3137
3140
}
3138
3141
}
3139
3142
3140
3143
/// 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 ( ) )
3144
+ pub fn check_path_modifications ( & self , paths : & [ & ' static str ] ) -> PathFreshness {
3145
+ // Checking path modifications through git can be relatively expensive (>100ms).
3146
+ // We do not assume that the sources would change during bootstrap's execution,
3147
+ // so we can cache the results here.
3148
+ // Note that we do not use a static variable for the cache, because it would cause problems
3149
+ // in tests that create separate `Config` instsances.
3150
+ self . path_modification_cache
3151
+ . lock ( )
3143
3152
. unwrap ( )
3153
+ . entry ( paths. to_vec ( ) )
3154
+ . or_insert_with ( || {
3155
+ check_path_modifications (
3156
+ Some ( & self . src ) ,
3157
+ & self . git_config ( ) ,
3158
+ paths,
3159
+ CiEnv :: current ( ) ,
3160
+ )
3161
+ . unwrap ( )
3162
+ } )
3163
+ . clone ( )
3144
3164
}
3145
3165
}
3146
3166
0 commit comments