Skip to content

Commit c5d879c

Browse files
committed
Port download-ci-rustc to check_path_modifications
And get rid of `get_closest_merge_commit`.
1 parent 297940a commit c5d879c

File tree

6 files changed

+38
-151
lines changed

6 files changed

+38
-151
lines changed

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,11 @@ impl Step for Std {
107107
// the `rust.download-rustc=true` option.
108108
let force_recompile = builder.rust_info().is_managed_git_subrepository()
109109
&& builder.download_rustc()
110-
&& builder.config.last_modified_commit(&["library"], "download-rustc", true).is_none();
110+
&& builder.config.has_changes_from_upstream(&["library"]);
111+
112+
trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
113+
trace!("download_rustc: {}", builder.download_rustc());
114+
trace!(force_recompile);
111115

112116
run.builder.ensure(Std {
113117
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -604,8 +604,7 @@ impl Step for Rustdoc {
604604
let files_to_track = &["src/librustdoc", "src/tools/rustdoc"];
605605

606606
// Check if unchanged
607-
if builder.config.last_modified_commit(files_to_track, "download-rustc", true).is_some()
608-
{
607+
if !builder.config.has_changes_from_upstream(files_to_track) {
609608
let precompiled_rustdoc = builder
610609
.config
611610
.ci_rustc_dir()

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

+8-2
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,14 @@ fn ci_rustc_if_unchanged_logic() {
261261
// Make sure "if-unchanged" logic doesn't try to use CI rustc while there are changes
262262
// in compiler and/or library.
263263
if config.download_rustc_commit.is_some() {
264-
let has_changes =
265-
config.last_modified_commit(&["compiler", "library"], "download-rustc", true).is_none();
264+
let mut paths = vec!["compiler"];
265+
266+
// Handle library tree the same way as in `Config::download_ci_rustc_commit`.
267+
if build_helper::ci::CiEnv::is_ci() {
268+
paths.push("library");
269+
}
270+
271+
let has_changes = config.has_changes_from_upstream(&paths);
266272

267273
assert!(
268274
!has_changes,

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

+19-74
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ use std::{cmp, env, fs};
1515

1616
use build_helper::ci::CiEnv;
1717
use build_helper::exit;
18-
use build_helper::git::{
19-
GitConfig, PathFreshness, check_path_modifications, get_closest_merge_commit, output_result,
20-
};
18+
use build_helper::git::{GitConfig, PathFreshness, check_path_modifications, output_result};
2119
use serde::{Deserialize, Deserializer};
2220
use serde_derive::Deserialize;
2321
#[cfg(feature = "tracing")]
@@ -2948,17 +2946,22 @@ impl Config {
29482946
let commit = if self.rust_info.is_managed_git_subrepository() {
29492947
// Look for a version to compare to based on the current commit.
29502948
// Only commits merged by bors will have CI artifacts.
2951-
match self.last_modified_commit(&allowed_paths, "download-rustc", if_unchanged) {
2952-
Some(commit) => commit,
2953-
None => {
2949+
match self.check_modifications(&allowed_paths) {
2950+
PathFreshness::LastModifiedUpstream { upstream } => upstream,
2951+
PathFreshness::HasLocalModifications { upstream } => {
29542952
if if_unchanged {
29552953
return None;
29562954
}
2957-
println!("ERROR: could not find commit hash for downloading rustc");
2958-
println!("HELP: maybe your repository history is too shallow?");
2959-
println!("HELP: consider setting `rust.download-rustc=false` in config.toml");
2960-
println!("HELP: or fetch enough history to include one upstream commit");
2961-
crate::exit!(1);
2955+
2956+
if CiEnv::is_ci() {
2957+
eprintln!("CI rustc commit matches with HEAD and we are in CI.");
2958+
eprintln!(
2959+
"`rustc.download-ci` functionality will be skipped as artifacts are not available."
2960+
);
2961+
return None;
2962+
}
2963+
2964+
upstream
29622965
}
29632966
}
29642967
} else {
@@ -2967,19 +2970,6 @@ impl Config {
29672970
.expect("git-commit-info is missing in the project root")
29682971
};
29692972

2970-
if CiEnv::is_ci() && {
2971-
let head_sha =
2972-
output(helpers::git(Some(&self.src)).arg("rev-parse").arg("HEAD").as_command_mut());
2973-
let head_sha = head_sha.trim();
2974-
commit == head_sha
2975-
} {
2976-
eprintln!("CI rustc commit matches with HEAD and we are in CI.");
2977-
eprintln!(
2978-
"`rustc.download-ci` functionality will be skipped as artifacts are not available."
2979-
);
2980-
return None;
2981-
}
2982-
29832973
if debug_assertions_requested {
29842974
eprintln!(
29852975
"WARN: `rust.debug-assertions = true` will prevent downloading CI rustc as alt CI \
@@ -3035,61 +3025,16 @@ impl Config {
30353025
}
30363026

30373027
/// Returns true if any of the `paths` have been modified locally.
3038-
fn has_changes_from_upstream(&self, paths: &[&str]) -> bool {
3039-
let freshness =
3040-
check_path_modifications(Some(&self.src), &self.git_config(), paths, CiEnv::current())
3041-
.unwrap();
3042-
match freshness {
3028+
pub fn has_changes_from_upstream(&self, paths: &[&str]) -> bool {
3029+
match self.check_modifications(paths) {
30433030
PathFreshness::LastModifiedUpstream { .. } => false,
30443031
PathFreshness::HasLocalModifications { .. } => true,
30453032
}
30463033
}
30473034

3048-
/// Returns the last commit in which any of `modified_paths` were changed,
3049-
/// or `None` if there are untracked changes in the working directory and `if_unchanged` is true.
3050-
pub fn last_modified_commit(
3051-
&self,
3052-
modified_paths: &[&str],
3053-
option_name: &str,
3054-
if_unchanged: bool,
3055-
) -> Option<String> {
3056-
assert!(
3057-
self.rust_info.is_managed_git_subrepository(),
3058-
"Can't run `Config::last_modified_commit` on a non-git source."
3059-
);
3060-
3061-
// Look for a version to compare to based on the current commit.
3062-
// Only commits merged by bors will have CI artifacts.
3063-
let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap();
3064-
if commit.is_empty() {
3065-
println!("error: could not find commit hash for downloading components from CI");
3066-
println!("help: maybe your repository history is too shallow?");
3067-
println!("help: consider disabling `{option_name}`");
3068-
println!("help: or fetch enough history to include one upstream commit");
3069-
crate::exit!(1);
3070-
}
3071-
3072-
// Warn if there were changes to the compiler or standard library since the ancestor commit.
3073-
let mut git = helpers::git(Some(&self.src));
3074-
git.args(["diff-index", "--quiet", &commit, "--"]).args(modified_paths);
3075-
3076-
let has_changes = !t!(git.as_command_mut().status()).success();
3077-
if has_changes {
3078-
if if_unchanged {
3079-
if self.is_verbose() {
3080-
println!(
3081-
"warning: saw changes to one of {modified_paths:?} since {commit}; \
3082-
ignoring `{option_name}`"
3083-
);
3084-
}
3085-
return None;
3086-
}
3087-
println!(
3088-
"warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}"
3089-
);
3090-
}
3091-
3092-
Some(commit.to_string())
3035+
fn check_modifications(&self, paths: &[&str]) -> PathFreshness {
3036+
check_path_modifications(Some(&self.src), &self.git_config(), paths, CiEnv::current())
3037+
.unwrap()
30933038
}
30943039
}
30953040

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

+1-3
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ fn download_ci_llvm() {
3939

4040
let if_unchanged_config = parse("llvm.download-ci-llvm = \"if-unchanged\"");
4141
if if_unchanged_config.llvm_from_ci {
42-
let has_changes = if_unchanged_config
43-
.last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true)
44-
.is_none();
42+
let has_changes = if_unchanged_config.has_changes_from_upstream(&["src/llvm-project"]);
4543

4644
assert!(
4745
!has_changes,

src/build_helper/src/git.rs

+4-69
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#[cfg(test)]
22
mod tests;
33

4-
use std::path::{Path, PathBuf};
4+
use std::path::Path;
55
use std::process::{Command, Stdio};
66

77
use crate::ci::CiEnv;
@@ -101,73 +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 that also exists upstream.
121-
///
122-
/// It looks for the most recent commit made by the merge bot by matching the author's email
123-
/// address with the merge bot's email.
124-
pub fn get_closest_merge_commit(
125-
git_dir: Option<&Path>,
126-
config: &GitConfig<'_>,
127-
target_paths: &[PathBuf],
128-
) -> Result<String, String> {
129-
let mut git = Command::new("git");
130-
131-
if let Some(git_dir) = git_dir {
132-
git.current_dir(git_dir);
133-
}
134-
135-
let channel = include_str!("../../ci/channel");
136-
137-
let merge_base = {
138-
if CiEnv::is_ci() &&
139-
// FIXME: When running on rust-lang managed CI and it's not a nightly build,
140-
// `git_upstream_merge_base` fails with an error message similar to this:
141-
// ```
142-
// called `Result::unwrap()` on an `Err` value: "command did not execute successfully:
143-
// cd \"/checkout\" && \"git\" \"merge-base\" \"origin/master\" \"HEAD\"\nexpected success, got: exit status: 1\n"
144-
// ```
145-
// Investigate and resolve this issue instead of skipping it like this.
146-
(channel == "nightly" || !CiEnv::is_rust_lang_managed_ci_job())
147-
{
148-
git_upstream_merge_base(config, git_dir).unwrap()
149-
} else {
150-
// For non-CI environments, ignore rust-lang/rust upstream as it usually gets
151-
// outdated very quickly.
152-
"HEAD".to_string()
153-
}
154-
};
155-
156-
git.args([
157-
"rev-list",
158-
&format!("--author={}", config.git_merge_commit_email),
159-
"-n1",
160-
"--first-parent",
161-
&merge_base,
162-
]);
163-
164-
if !target_paths.is_empty() {
165-
git.arg("--").args(target_paths);
166-
}
167-
168-
Ok(output_result(&mut git)?.trim().to_owned())
169-
}
170-
171104
/// Represents the result of checking whether a set of paths
172105
/// have been modified locally or not.
173106
#[derive(PartialEq, Debug)]
@@ -184,10 +117,12 @@ pub enum PathFreshness {
184117

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

0 commit comments

Comments
 (0)