Use check_path_modifications for detecting local LLVM changes

This commit is contained in:
Jakub Beránek 2025-03-21 22:23:37 +01:00
parent 1d1f248093
commit 0396f0e522
6 changed files with 50 additions and 20 deletions

View file

@ -17,7 +17,6 @@ use crate::core::config::TargetSelection;
use crate::utils::build_stamp::{BuildStamp, generate_smart_stamp_hash};
use crate::utils::exec::command;
use crate::utils::helpers::{self, t};
use build_helper::git::PathFreshness;
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Gcc {
@ -97,6 +96,8 @@ pub enum GccBuildStatus {
/// Returns a path to the libgccjit.so file.
#[cfg(not(test))]
fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option<PathBuf> {
use build_helper::git::PathFreshness;
// Try to download GCC from CI if configured and available
if !matches!(builder.config.gcc_ci_mode, crate::core::config::GccCiMode::DownloadFromCi) {
return None;

View file

@ -14,7 +14,7 @@ use std::path::{Path, PathBuf};
use std::sync::OnceLock;
use std::{env, fs};
use build_helper::git::get_closest_merge_commit;
use build_helper::git::{PathFreshness, check_path_modifications};
#[cfg(feature = "tracing")]
use tracing::instrument;
@ -181,26 +181,33 @@ pub const LLVM_INVALIDATION_PATHS: &[&str] = &[
"src/version",
];
/// 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 {
get_closest_merge_commit(Some(&config.src), &config.git_config(), LLVM_INVALIDATION_PATHS)
.unwrap()
/// Detect whether LLVM sources have been modified locally or not.
pub(crate) fn detect_llvm_freshness(config: &Config, is_git: bool) -> PathFreshness {
let freshness = if is_git {
Some(
check_path_modifications(
Some(&config.src),
&config.git_config(),
LLVM_INVALIDATION_PATHS,
config.ci_env(),
)
.unwrap(),
)
} else if let Some(info) = crate::utils::channel::read_commit_info_file(&config.src) {
info.sha.trim().to_owned()
Some(PathFreshness::LastModifiedUpstream { upstream: info.sha.trim().to_owned() })
} else {
"".to_owned()
None
};
if llvm_sha.is_empty() {
let Some(freshness) = freshness else {
eprintln!("error: could not find commit hash for downloading LLVM");
eprintln!("HELP: maybe your repository history is too shallow?");
eprintln!("HELP: consider disabling `download-ci-llvm`");
eprintln!("HELP: or fetch enough history to include one upstream commit");
panic!();
}
};
llvm_sha
freshness
}
/// Returns whether the CI-found LLVM is currently usable.

View file

@ -16,7 +16,9 @@ use std::{cmp, env, fs};
use build_helper::ci::CiEnv;
use build_helper::exit;
use build_helper::git::{GitConfig, get_closest_merge_commit, output_result};
use build_helper::git::{
GitConfig, PathFreshness, check_path_modifications, get_closest_merge_commit, output_result,
};
use serde::{Deserialize, Deserializer};
use serde_derive::Deserialize;
#[cfg(feature = "tracing")]
@ -3264,9 +3266,7 @@ impl Config {
self.update_submodule("src/llvm-project");
// Check for untracked changes in `src/llvm-project` and other important places.
let has_changes = self
.last_modified_commit(LLVM_INVALIDATION_PATHS, "download-ci-llvm", true)
.is_none();
let has_changes = self.has_changes_from_upstream(LLVM_INVALIDATION_PATHS);
// Return false if there are untracked changes, otherwise check if CI LLVM is available.
if has_changes { false } else { llvm::is_ci_llvm_available_for_target(self, asserts) }
@ -3297,6 +3297,17 @@ impl Config {
}
}
/// Returns true if any of the `paths` have been modified locally.
fn has_changes_from_upstream(&self, paths: &[&str]) -> bool {
let freshness =
check_path_modifications(Some(&self.src), &self.git_config(), paths, CiEnv::current())
.unwrap();
match freshness {
PathFreshness::LastModifiedUpstream { .. } => false,
PathFreshness::HasLocalModifications { .. } => true,
}
}
/// Returns the last commit in which any of `modified_paths` were changed,
/// or `None` if there are untracked changes in the working directory and `if_unchanged` is true.
pub fn last_modified_commit(

View file

@ -720,8 +720,9 @@ download-rustc = false
#[cfg(not(test))]
pub(crate) fn maybe_download_ci_llvm(&self) {
use build_helper::exit;
use build_helper::git::PathFreshness;
use crate::core::build_steps::llvm::detect_llvm_sha;
use crate::core::build_steps::llvm::detect_llvm_freshness;
use crate::core::config::check_incompatible_options_for_ci_llvm;
if !self.llvm_from_ci {
@ -729,7 +730,11 @@ download-rustc = false
}
let llvm_root = self.ci_llvm_root();
let llvm_sha = detect_llvm_sha(self, self.rust_info.is_managed_git_subrepository());
let llvm_sha =
match detect_llvm_freshness(self, self.rust_info.is_managed_git_subrepository()) {
PathFreshness::LastModifiedUpstream { upstream } => upstream,
PathFreshness::HasLocalModifications { upstream } => upstream,
};
let stamp_key = format!("{}{}", llvm_sha, self.llvm_assertions);
let llvm_stamp = BuildStamp::new(&llvm_root).with_prefix("llvm").add_stamp(stamp_key);
if !llvm_stamp.is_up_to_date() && !self.dry_run() {

View file

@ -261,6 +261,11 @@ pub fn check_path_modifications(
upstream_sha
};
// For local environments, we want to find out if something has changed
// from the latest upstream commit.
// However, that should be equivalent to checking if something has changed
// from the latest upstream commit *that modified `target_paths`*, and
// with this approach we do not need to invoke git an additional time.
if has_changed_since(git_dir, &upstream_sha, target_paths) {
Ok(PathFreshness::HasLocalModifications { upstream: upstream_sha })
} else {

View file

@ -1,9 +1,10 @@
use crate::ci::CiEnv;
use crate::git::{GitConfig, PathFreshness, check_path_modifications};
use std::ffi::OsStr;
use std::fs::OpenOptions;
use std::process::Command;
use crate::ci::CiEnv;
use crate::git::{GitConfig, PathFreshness, check_path_modifications};
#[test]
fn test_pr_ci_unchanged_anywhere() {
git_test(|ctx| {