From 1b5921641a39e28d97549ced449476c1d325f0ec Mon Sep 17 00:00:00 2001
From: guliwa <torricelli@126.com>
Date: Sun, 29 Sep 2024 22:09:56 +0000
Subject: [PATCH] Refactor change detection for rustdoc and download-rustc

---
 src/bootstrap/src/core/build_steps/tool.rs | 31 +++---------
 src/bootstrap/src/core/config/config.rs    | 58 +++++++---------------
 2 files changed, 23 insertions(+), 66 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 50f71e167db9f..bb837eb81379a 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -1,8 +1,6 @@
 use std::path::PathBuf;
 use std::{env, fs};
 
-use build_helper::git::get_closest_merge_commit;
-
 use crate::core::build_steps::compile;
 use crate::core::build_steps::toolstate::ToolState;
 use crate::core::builder;
@@ -10,7 +8,7 @@ use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun,
 use crate::core::config::TargetSelection;
 use crate::utils::channel::GitInfo;
 use crate::utils::exec::{BootstrapCommand, command};
-use crate::utils::helpers::{add_dylib_path, exe, git, t};
+use crate::utils::helpers::{add_dylib_path, exe, t};
 use crate::{Compiler, Kind, Mode, gha};
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -596,28 +594,11 @@ impl Step for Rustdoc {
             && target_compiler.stage > 0
             && builder.rust_info().is_managed_git_subrepository()
         {
-            let commit = get_closest_merge_commit(
-                Some(&builder.config.src),
-                &builder.config.git_config(),
-                &[],
-            )
-            .unwrap();
-
-            let librustdoc_src = builder.config.src.join("src/librustdoc");
-            let rustdoc_src = builder.config.src.join("src/tools/rustdoc");
-
-            // FIXME: The change detection logic here is quite similar to `Config::download_ci_rustc_commit`.
-            // It would be better to unify them.
-            let has_changes = !git(Some(&builder.config.src))
-                .allow_failure()
-                .run_always()
-                .args(["diff-index", "--quiet", &commit])
-                .arg("--")
-                .arg(librustdoc_src)
-                .arg(rustdoc_src)
-                .run(builder);
-
-            if !has_changes {
+            let files_to_track = &["src/librustdoc", "src/tools/rustdoc"];
+
+            // Check if unchanged
+            if builder.config.last_modified_commit(files_to_track, "download-rustc", true).is_some()
+            {
                 let precompiled_rustdoc = builder
                     .config
                     .ci_rustc_dir()
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index aeb81b146382e..9466b046a6564 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -2754,25 +2754,25 @@ impl Config {
             }
         };
 
-        let files_to_track = &[
-            self.src.join("compiler"),
-            self.src.join("library"),
-            self.src.join("src/version"),
-            self.src.join("src/stage0"),
-            self.src.join("src/ci/channel"),
-        ];
+        let files_to_track =
+            &["compiler", "library", "src/version", "src/stage0", "src/ci/channel"];
 
         // Look for a version to compare to based on the current commit.
         // Only commits merged by bors will have CI artifacts.
-        let commit =
-            get_closest_merge_commit(Some(&self.src), &self.git_config(), files_to_track).unwrap();
-        if commit.is_empty() {
-            println!("ERROR: could not find commit hash for downloading rustc");
-            println!("HELP: maybe your repository history is too shallow?");
-            println!("HELP: consider disabling `download-rustc`");
-            println!("HELP: or fetch enough history to include one upstream commit");
-            crate::exit!(1);
-        }
+        let commit = match self.last_modified_commit(files_to_track, "download-rustc", if_unchanged)
+        {
+            Some(commit) => commit,
+            None => {
+                if if_unchanged {
+                    return None;
+                }
+                println!("ERROR: could not find commit hash for downloading rustc");
+                println!("HELP: maybe your repository history is too shallow?");
+                println!("HELP: consider disabling `download-rustc`");
+                println!("HELP: or fetch enough history to include one upstream commit");
+                crate::exit!(1);
+            }
+        };
 
         if CiEnv::is_ci() && {
             let head_sha =
@@ -2787,31 +2787,7 @@ impl Config {
             return None;
         }
 
-        // Warn if there were changes to the compiler or standard library since the ancestor commit.
-        let has_changes = !t!(helpers::git(Some(&self.src))
-            .args(["diff-index", "--quiet", &commit])
-            .arg("--")
-            .args(files_to_track)
-            .as_command_mut()
-            .status())
-        .success();
-        if has_changes {
-            if if_unchanged {
-                if self.is_verbose() {
-                    println!(
-                        "WARNING: saw changes to compiler/ or library/ since {commit}; \
-                            ignoring `download-rustc`"
-                    );
-                }
-                return None;
-            }
-            println!(
-                "WARNING: `download-rustc` is enabled, but there are changes to \
-                    compiler/ or library/"
-            );
-        }
-
-        Some(commit.to_string())
+        Some(commit)
     }
 
     fn parse_download_ci_llvm(