Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 2228033

Browse files
committed
Use check_path_modifications for detecting local rustc changes
And get rid of `get_closest_merge_commit`.
1 parent 0396f0e commit 2228033

File tree

6 files changed

+26
-157
lines changed

6 files changed

+26
-157
lines changed

src/bootstrap/src/core/build_steps/compile.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,10 @@ impl Step for Std {
111111
// the `rust.download-rustc=true` option.
112112
let force_recompile = builder.rust_info().is_managed_git_subrepository()
113113
&& builder.download_rustc()
114-
&& builder.config.last_modified_commit(&["library"], "download-rustc", true).is_none();
114+
&& builder.config.has_changes_from_upstream(&["library"]);
115115

116116
trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
117117
trace!("download_rustc: {}", builder.download_rustc());
118-
trace!(
119-
"last modified commit: {:?}",
120-
builder.config.last_modified_commit(&["library"], "download-rustc", true)
121-
);
122118
trace!(force_recompile);
123119

124120
run.builder.ensure(Std {

src/bootstrap/src/core/build_steps/tool.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -696,8 +696,7 @@ impl Step for Rustdoc {
696696
let files_to_track = &["src/librustdoc", "src/tools/rustdoc"];
697697

698698
// Check if unchanged
699-
if builder.config.last_modified_commit(files_to_track, "download-rustc", true).is_some()
700-
{
699+
if !builder.config.has_changes_from_upstream(files_to_track) {
701700
let precompiled_rustdoc = builder
702701
.config
703702
.ci_rustc_dir()

src/bootstrap/src/core/builder/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ fn ci_rustc_if_unchanged_logic() {
268268
paths.push("library");
269269
}
270270

271-
let has_changes = config.last_modified_commit(&paths, "download-rustc", true).is_none();
271+
let has_changes = config.has_changes_from_upstream(&paths);
272272

273273
assert!(
274274
!has_changes,

src/bootstrap/src/core/config/config.rs

Lines changed: 19 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ use std::{cmp, env, fs};
1616

1717
use build_helper::ci::CiEnv;
1818
use build_helper::exit;
19-
use build_helper::git::{
20-
GitConfig, PathFreshness, check_path_modifications, get_closest_merge_commit, output_result,
21-
};
19+
use build_helper::git::{GitConfig, PathFreshness, check_path_modifications, output_result};
2220
use serde::{Deserialize, Deserializer};
2321
use serde_derive::Deserialize;
2422
#[cfg(feature = "tracing")]
@@ -3195,19 +3193,22 @@ impl Config {
31953193
let commit = if self.rust_info.is_managed_git_subrepository() {
31963194
// Look for a version to compare to based on the current commit.
31973195
// Only commits merged by bors will have CI artifacts.
3198-
match self.last_modified_commit(&allowed_paths, "download-rustc", if_unchanged) {
3199-
Some(commit) => commit,
3200-
None => {
3196+
match self.check_modifications(&allowed_paths) {
3197+
PathFreshness::LastModifiedUpstream { upstream } => upstream,
3198+
PathFreshness::HasLocalModifications { upstream } => {
32013199
if if_unchanged {
32023200
return None;
32033201
}
3204-
println!("ERROR: could not find commit hash for downloading rustc");
3205-
println!("HELP: maybe your repository history is too shallow?");
3206-
println!(
3207-
"HELP: consider setting `rust.download-rustc=false` in bootstrap.toml"
3208-
);
3209-
println!("HELP: or fetch enough history to include one upstream commit");
3210-
crate::exit!(1);
3202+
3203+
if self.is_running_on_ci {
3204+
eprintln!("CI rustc commit matches with HEAD and we are in CI.");
3205+
eprintln!(
3206+
"`rustc.download-ci` functionality will be skipped as artifacts are not available."
3207+
);
3208+
return None;
3209+
}
3210+
3211+
upstream
32113212
}
32123213
}
32133214
} else {
@@ -3216,19 +3217,6 @@ impl Config {
32163217
.expect("git-commit-info is missing in the project root")
32173218
};
32183219

3219-
if self.is_running_on_ci && {
3220-
let head_sha =
3221-
output(helpers::git(Some(&self.src)).arg("rev-parse").arg("HEAD").as_command_mut());
3222-
let head_sha = head_sha.trim();
3223-
commit == head_sha
3224-
} {
3225-
eprintln!("CI rustc commit matches with HEAD and we are in CI.");
3226-
eprintln!(
3227-
"`rustc.download-ci` functionality will be skipped as artifacts are not available."
3228-
);
3229-
return None;
3230-
}
3231-
32323220
if debug_assertions_requested {
32333221
eprintln!(
32343222
"WARN: `rust.debug-assertions = true` will prevent downloading CI rustc as alt CI \
@@ -3298,61 +3286,16 @@ impl Config {
32983286
}
32993287

33003288
/// Returns true if any of the `paths` have been modified locally.
3301-
fn has_changes_from_upstream(&self, paths: &[&str]) -> bool {
3302-
let freshness =
3303-
check_path_modifications(Some(&self.src), &self.git_config(), paths, CiEnv::current())
3304-
.unwrap();
3305-
match freshness {
3289+
pub fn has_changes_from_upstream(&self, paths: &[&str]) -> bool {
3290+
match self.check_modifications(paths) {
33063291
PathFreshness::LastModifiedUpstream { .. } => false,
33073292
PathFreshness::HasLocalModifications { .. } => true,
33083293
}
33093294
}
33103295

3311-
/// Returns the last commit in which any of `modified_paths` were changed,
3312-
/// or `None` if there are untracked changes in the working directory and `if_unchanged` is true.
3313-
pub fn last_modified_commit(
3314-
&self,
3315-
modified_paths: &[&str],
3316-
option_name: &str,
3317-
if_unchanged: bool,
3318-
) -> Option<String> {
3319-
assert!(
3320-
self.rust_info.is_managed_git_subrepository(),
3321-
"Can't run `Config::last_modified_commit` on a non-git source."
3322-
);
3323-
3324-
// Look for a version to compare to based on the current commit.
3325-
// Only commits merged by bors will have CI artifacts.
3326-
let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap();
3327-
if commit.is_empty() {
3328-
println!("error: could not find commit hash for downloading components from CI");
3329-
println!("help: maybe your repository history is too shallow?");
3330-
println!("help: consider disabling `{option_name}`");
3331-
println!("help: or fetch enough history to include one upstream commit");
3332-
crate::exit!(1);
3333-
}
3334-
3335-
// Warn if there were changes to the compiler or standard library since the ancestor commit.
3336-
let mut git = helpers::git(Some(&self.src));
3337-
git.args(["diff-index", "--quiet", &commit, "--"]).args(modified_paths);
3338-
3339-
let has_changes = !t!(git.as_command_mut().status()).success();
3340-
if has_changes {
3341-
if if_unchanged {
3342-
if self.is_verbose() {
3343-
println!(
3344-
"warning: saw changes to one of {modified_paths:?} since {commit}; \
3345-
ignoring `{option_name}`"
3346-
);
3347-
}
3348-
return None;
3349-
}
3350-
println!(
3351-
"warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}"
3352-
);
3353-
}
3354-
3355-
Some(commit.to_string())
3296+
fn check_modifications(&self, paths: &[&str]) -> PathFreshness {
3297+
check_path_modifications(Some(&self.src), &self.git_config(), paths, CiEnv::current())
3298+
.unwrap()
33563299
}
33573300

33583301
/// Checks if the given target is the same as the host target.

src/bootstrap/src/core/config/tests.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,7 @@ fn download_ci_llvm() {
5151

5252
let if_unchanged_config = parse("llvm.download-ci-llvm = \"if-unchanged\"");
5353
if if_unchanged_config.llvm_from_ci && if_unchanged_config.is_running_on_ci {
54-
let has_changes = if_unchanged_config
55-
.last_modified_commit(LLVM_INVALIDATION_PATHS, "download-ci-llvm", true)
56-
.is_none();
54+
let has_changes = if_unchanged_config.has_changes_from_upstream(&["src/llvm-project"]);
5755

5856
assert!(
5957
!has_changes,

src/build_helper/src/git.rs

Lines changed: 3 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -101,75 +101,6 @@ pub fn updated_master_branch(
101101
Err("Cannot find any suitable upstream master branch".to_owned())
102102
}
103103

104-
/// Finds the nearest merge commit by comparing the local `HEAD` with the upstream branch's state.
105-
/// To work correctly, the upstream remote must be properly configured using `git remote add <name> <url>`.
106-
/// In most cases `get_closest_merge_commit` is the function you are looking for as it doesn't require remote
107-
/// to be configured.
108-
fn git_upstream_merge_base(
109-
config: &GitConfig<'_>,
110-
git_dir: Option<&Path>,
111-
) -> Result<String, String> {
112-
let updated_master = updated_master_branch(config, git_dir)?;
113-
let mut git = Command::new("git");
114-
if let Some(git_dir) = git_dir {
115-
git.current_dir(git_dir);
116-
}
117-
Ok(output_result(git.arg("merge-base").arg(&updated_master).arg("HEAD"))?.trim().to_owned())
118-
}
119-
120-
/// Searches for the nearest merge commit in the repository.
121-
///
122-
/// **In CI** finds the nearest merge commit that *also exists upstream*.
123-
///
124-
/// It looks for the most recent commit made by the merge bot by matching the author's email
125-
/// address with the merge bot's email.
126-
pub fn get_closest_merge_commit(
127-
git_dir: Option<&Path>,
128-
config: &GitConfig<'_>,
129-
target_paths: &[&str],
130-
) -> Result<String, String> {
131-
let mut git = Command::new("git");
132-
133-
if let Some(git_dir) = git_dir {
134-
git.current_dir(git_dir);
135-
}
136-
137-
let channel = include_str!("../../ci/channel").trim();
138-
139-
let merge_base = {
140-
if CiEnv::is_ci() &&
141-
// FIXME: When running on rust-lang managed CI and it's not a nightly build,
142-
// `git_upstream_merge_base` fails with an error message similar to this:
143-
// ```
144-
// called `Result::unwrap()` on an `Err` value: "command did not execute successfully:
145-
// cd \"/checkout\" && \"git\" \"merge-base\" \"origin/master\" \"HEAD\"\nexpected success, got: exit status: 1\n"
146-
// ```
147-
// Investigate and resolve this issue instead of skipping it like this.
148-
(channel == "nightly" || !CiEnv::is_rust_lang_managed_ci_job())
149-
{
150-
git_upstream_merge_base(config, git_dir).unwrap()
151-
} else {
152-
// For non-CI environments, ignore rust-lang/rust upstream as it usually gets
153-
// outdated very quickly.
154-
"HEAD".to_string()
155-
}
156-
};
157-
158-
git.args([
159-
"rev-list",
160-
&format!("--author={}", config.git_merge_commit_email),
161-
"-n1",
162-
"--first-parent",
163-
&merge_base,
164-
]);
165-
166-
if !target_paths.is_empty() {
167-
git.arg("--").args(target_paths);
168-
}
169-
170-
Ok(output_result(&mut git)?.trim().to_owned())
171-
}
172-
173104
/// Represents the result of checking whether a set of paths
174105
/// have been modified locally or not.
175106
#[derive(PartialEq, Debug)]
@@ -186,10 +117,12 @@ pub enum PathFreshness {
186117

187118
/// This function figures out if a set of paths was last modified upstream or
188119
/// if there are some local modifications made to them.
189-
///
190120
/// It can be used to figure out if we should download artifacts from CI or rather
191121
/// build them locally.
192122
///
123+
/// The function assumes that at least a single upstream bors merge commit is in the
124+
/// local git history.
125+
///
193126
/// `target_paths` should be a non-empty slice of paths (git `pathspec`s) relative to `git_dir`
194127
/// or the current working directory whose modifications would invalidate the artifact.
195128
/// Each pathspec can also be a negative match, i.e. `:!foo`. This matches changes outside

0 commit comments

Comments
 (0)