@@ -947,7 +947,14 @@ impl Config {
947
947
) ;
948
948
}
949
949
950
- config. download_rustc_commit = config. download_ci_rustc_commit (
950
+ config. download_rustc_commit = download_ci_rustc_commit (
951
+ & config. stage0_metadata ,
952
+ config. path_modification_cache . clone ( ) ,
953
+ & config. src ,
954
+ config. is_running_on_ci ,
955
+ & config. exec_ctx ,
956
+ & config. rust_info ,
957
+ & config. host_target ,
951
958
rust_download_rustc,
952
959
debug_assertions_requested,
953
960
config. llvm_assertions ,
@@ -2335,3 +2342,123 @@ pub fn check_stage0_version(
2335
2342
) ) ;
2336
2343
}
2337
2344
}
2345
+
2346
+ pub fn download_ci_rustc_commit (
2347
+ stage0_metadata : & build_helper:: stage0_parser:: Stage0 ,
2348
+ path_modification_cache : Arc < Mutex < HashMap < Vec < & ' static str > , PathFreshness > > > ,
2349
+ src : & Path ,
2350
+ is_running_on_ci : bool ,
2351
+ exec_ctx : & ExecutionContext ,
2352
+ rust_info : & channel:: GitInfo ,
2353
+ host_target : & TargetSelection ,
2354
+ download_rustc : Option < StringOrBool > ,
2355
+ debug_assertions_requested : bool ,
2356
+ llvm_assertions : bool ,
2357
+ ) -> Option < String > {
2358
+ if !is_download_ci_available ( & host_target. triple , llvm_assertions) {
2359
+ return None ;
2360
+ }
2361
+
2362
+ // If `download-rustc` is not set, default to rebuilding.
2363
+ let if_unchanged = match download_rustc {
2364
+ // Globally default `download-rustc` to `false`, because some contributors don't use
2365
+ // profiles for reasons such as:
2366
+ // - They need to seamlessly switch between compiler/library work.
2367
+ // - They don't want to use compiler profile because they need to override too many
2368
+ // things and it's easier to not use a profile.
2369
+ None | Some ( StringOrBool :: Bool ( false ) ) => return None ,
2370
+ Some ( StringOrBool :: Bool ( true ) ) => false ,
2371
+ Some ( StringOrBool :: String ( s) ) if s == "if-unchanged" => {
2372
+ if !rust_info. is_managed_git_subrepository ( ) {
2373
+ println ! (
2374
+ "ERROR: `download-rustc=if-unchanged` is only compatible with Git managed sources."
2375
+ ) ;
2376
+ crate :: exit!( 1 ) ;
2377
+ }
2378
+
2379
+ true
2380
+ }
2381
+ Some ( StringOrBool :: String ( other) ) => {
2382
+ panic ! ( "unrecognized option for download-rustc: {other}" )
2383
+ }
2384
+ } ;
2385
+
2386
+ let commit = if rust_info. is_managed_git_subrepository ( ) {
2387
+ // Look for a version to compare to based on the current commit.
2388
+ // Only commits merged by bors will have CI artifacts.
2389
+ let freshness = check_path_modifications_ (
2390
+ stage0_metadata,
2391
+ src,
2392
+ path_modification_cache,
2393
+ RUSTC_IF_UNCHANGED_ALLOWED_PATHS ,
2394
+ ) ;
2395
+ exec_ctx. verbose ( || {
2396
+ eprintln ! ( "rustc freshness: {freshness:?}" ) ;
2397
+ } ) ;
2398
+ match freshness {
2399
+ PathFreshness :: LastModifiedUpstream { upstream } => upstream,
2400
+ PathFreshness :: HasLocalModifications { upstream } => {
2401
+ if if_unchanged {
2402
+ return None ;
2403
+ }
2404
+
2405
+ if is_running_on_ci {
2406
+ eprintln ! ( "CI rustc commit matches with HEAD and we are in CI." ) ;
2407
+ eprintln ! (
2408
+ "`rustc.download-ci` functionality will be skipped as artifacts are not available."
2409
+ ) ;
2410
+ return None ;
2411
+ }
2412
+
2413
+ upstream
2414
+ }
2415
+ PathFreshness :: MissingUpstream => {
2416
+ eprintln ! ( "No upstream commit found" ) ;
2417
+ return None ;
2418
+ }
2419
+ }
2420
+ } else {
2421
+ channel:: read_commit_info_file ( src)
2422
+ . map ( |info| info. sha . trim ( ) . to_owned ( ) )
2423
+ . expect ( "git-commit-info is missing in the project root" )
2424
+ } ;
2425
+
2426
+ if debug_assertions_requested {
2427
+ eprintln ! (
2428
+ "WARN: `rust.debug-assertions = true` will prevent downloading CI rustc as alt CI \
2429
+ rustc is not currently built with debug assertions."
2430
+ ) ;
2431
+ return None ;
2432
+ }
2433
+
2434
+ Some ( commit)
2435
+ }
2436
+
2437
+ pub fn check_path_modifications_ (
2438
+ stage0_metadata : & build_helper:: stage0_parser:: Stage0 ,
2439
+ src : & Path ,
2440
+ path_modification_cache : Arc < Mutex < HashMap < Vec < & ' static str > , PathFreshness > > > ,
2441
+ paths : & [ & ' static str ] ,
2442
+ ) -> PathFreshness {
2443
+ // Checking path modifications through git can be relatively expensive (>100ms).
2444
+ // We do not assume that the sources would change during bootstrap's execution,
2445
+ // so we can cache the results here.
2446
+ // Note that we do not use a static variable for the cache, because it would cause problems
2447
+ // in tests that create separate `Config` instsances.
2448
+ path_modification_cache
2449
+ . lock ( )
2450
+ . unwrap ( )
2451
+ . entry ( paths. to_vec ( ) )
2452
+ . or_insert_with ( || {
2453
+ check_path_modifications ( src, & git_config ( stage0_metadata) , paths, CiEnv :: current ( ) )
2454
+ . unwrap ( )
2455
+ } )
2456
+ . clone ( )
2457
+ }
2458
+
2459
+ pub fn git_config ( stage0_metadata : & build_helper:: stage0_parser:: Stage0 ) -> GitConfig < ' _ > {
2460
+ GitConfig {
2461
+ nightly_branch : & stage0_metadata. config . nightly_branch ,
2462
+ git_merge_commit_email : & stage0_metadata. config . git_merge_commit_email ,
2463
+ }
2464
+ }
0 commit comments