abstract merge-base commit logic

Signed-off-by: onur-ozkan <work@onurozkan.dev>
This commit is contained in:
onur-ozkan 2024-07-17 18:14:54 +03:00
parent cb12b52f16
commit 2b5a9821eb
4 changed files with 54 additions and 41 deletions

View File

@ -26,7 +26,6 @@ use crate::{generate_smart_stamp_hash, CLang, GitRepo, Kind};
use crate::utils::exec::command;
use build_helper::ci::CiEnv;
use build_helper::git::get_git_merge_base;
#[derive(Clone)]
pub struct LlvmResult {
@ -154,26 +153,18 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L
/// This retrieves the LLVM sha we *want* to use, according to git history.
pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String {
let llvm_sha = if is_git {
// We proceed in 2 steps. First we get the closest commit that is actually upstream. Then we
// walk back further to the last bors merge commit that actually changed LLVM. The first
// step will fail on CI because only the `auto` branch exists; we just fall back to `HEAD`
// in that case.
let closest_upstream = get_git_merge_base(&config.git_config(), Some(&config.src))
.unwrap_or_else(|_| "HEAD".into());
let mut rev_list = helpers::git(Some(&config.src));
rev_list.args(&[
PathBuf::from("rev-list"),
format!("--author={}", config.stage0_metadata.config.git_merge_commit_email).into(),
"-n1".into(),
"--first-parent".into(),
closest_upstream.into(),
"--".into(),
config.src.join("src/llvm-project"),
config.src.join("src/bootstrap/download-ci-llvm-stamp"),
// the LLVM shared object file is named `LLVM-12-rust-{version}-nightly`
config.src.join("src/version"),
]);
output(rev_list.as_command_mut()).trim().to_owned()
helpers::get_closest_merge_base_commit(
Some(&config.src),
&config.git_config(),
&config.stage0_metadata.config.git_merge_commit_email,
&[
config.src.join("src/llvm-project"),
config.src.join("src/bootstrap/download-ci-llvm-stamp"),
// the LLVM shared object file is named `LLVM-12-rust-{version}-nightly`
config.src.join("src/version"),
],
)
.unwrap()
} else if let Some(info) = channel::read_commit_info_file(&config.src) {
info.sha.trim().to_owned()
} else {

View File

@ -20,7 +20,7 @@ use crate::core::build_steps::llvm;
use crate::core::config::flags::{Color, Flags, Warnings};
use crate::utils::cache::{Interned, INTERNER};
use crate::utils::channel::{self, GitInfo};
use crate::utils::helpers::{self, exe, output, t};
use crate::utils::helpers::{self, exe, get_closest_merge_base_commit, output, t};
use build_helper::exit;
use serde::{Deserialize, Deserializer};
use serde_derive::Deserialize;
@ -2471,14 +2471,13 @@ impl Config {
// Look for a version to compare to based on the current commit.
// Only commits merged by bors will have CI artifacts.
let merge_base = output(
helpers::git(Some(&self.src))
.arg("rev-list")
.arg(format!("--author={}", self.stage0_metadata.config.git_merge_commit_email))
.args(["-n1", "--first-parent", "HEAD"])
.as_command_mut(),
);
let commit = merge_base.trim_end();
let commit = get_closest_merge_base_commit(
Some(&self.src),
&self.git_config(),
&self.stage0_metadata.config.git_merge_commit_email,
&[],
)
.unwrap();
if commit.is_empty() {
println!("ERROR: could not find commit hash for downloading rustc");
println!("HELP: maybe your repository history is too shallow?");
@ -2489,7 +2488,7 @@ impl Config {
// 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])
.args(["diff-index", "--quiet", &commit])
.arg("--")
.args([self.src.join("compiler"), self.src.join("library")])
.as_command_mut()
@ -2565,14 +2564,13 @@ impl Config {
) -> Option<String> {
// Look for a version to compare to based on the current commit.
// Only commits merged by bors will have CI artifacts.
let merge_base = output(
helpers::git(Some(&self.src))
.arg("rev-list")
.arg(format!("--author={}", self.stage0_metadata.config.git_merge_commit_email))
.args(["-n1", "--first-parent", "HEAD"])
.as_command_mut(),
);
let commit = merge_base.trim_end();
let commit = get_closest_merge_base_commit(
Some(&self.src),
&self.git_config(),
&self.stage0_metadata.config.git_merge_commit_email,
&[],
)
.unwrap();
if commit.is_empty() {
println!("error: could not find commit hash for downloading components from CI");
println!("help: maybe your repository history is too shallow?");
@ -2583,7 +2581,7 @@ impl Config {
// Warn if there were changes to the compiler or standard library since the ancestor commit.
let mut git = helpers::git(Some(&self.src));
git.args(["diff-index", "--quiet", commit, "--"]);
git.args(["diff-index", "--quiet", &commit, "--"]);
// Handle running from a directory other than the top level
let top_level = &self.src;

View File

@ -3,6 +3,7 @@
//! Simple things like testing the various filesystem operations here and there,
//! not a lot of interesting happenings here unfortunately.
use build_helper::git::{get_git_merge_base, output_result, GitConfig};
use build_helper::util::fail;
use std::env;
use std::ffi::OsStr;
@ -521,3 +522,26 @@ pub fn git(source_dir: Option<&Path>) -> BootstrapCommand {
git
}
/// Returns the closest commit available from upstream for the given `author` and `target_paths`.
///
/// If it fails to find the commit from upstream using `git merge-base`, fallbacks to HEAD.
pub fn get_closest_merge_base_commit(
source_dir: Option<&Path>,
config: &GitConfig<'_>,
author: &str,
target_paths: &[PathBuf],
) -> Result<String, String> {
let mut git = git(source_dir).capture_stdout();
let merge_base = get_git_merge_base(config, source_dir).unwrap_or_else(|_| "HEAD".into());
git.arg(Path::new("rev-list"));
git.args([&format!("--author={author}"), "-n1", "--first-parent", &merge_base]);
if !target_paths.is_empty() {
git.arg("--").args(target_paths);
}
Ok(output_result(git.as_command_mut())?.trim().to_owned())
}

View File

@ -7,7 +7,7 @@ pub struct GitConfig<'a> {
}
/// Runs a command and returns the output
fn output_result(cmd: &mut Command) -> Result<String, String> {
pub fn output_result(cmd: &mut Command) -> Result<String, String> {
let output = match cmd.stderr(Stdio::inherit()).output() {
Ok(status) => status,
Err(e) => return Err(format!("failed to run command: {:?}: {}", cmd, e)),