Skip to content

Commit cf6df56

Browse files
committed
rustc_tools_util: rerun when git commit changes
1 parent a81f1c8 commit cf6df56

File tree

1 file changed

+36
-4
lines changed

1 file changed

+36
-4
lines changed

rustc_tools_util/src/lib.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::path::PathBuf;
2+
use std::process::Command;
13
use std::str;
24

35
/// This macro creates the version string during compilation from the
@@ -32,6 +34,7 @@ macro_rules! get_version_info {
3234
#[macro_export]
3335
macro_rules! setup_version_info {
3436
() => {{
37+
let _ = $crate::rerun_if_git_changes();
3538
println!(
3639
"cargo:rustc-env=GIT_HASH={}",
3740
$crate::get_commit_hash().unwrap_or_default()
@@ -100,19 +103,48 @@ impl std::fmt::Debug for VersionInfo {
100103
}
101104

102105
#[must_use]
103-
pub fn get_commit_hash() -> Option<String> {
104-
let output = std::process::Command::new("git")
105-
.args(["rev-parse", "HEAD"])
106+
pub fn rerun_if_git_changes() -> Option<()> {
107+
// Make sure we get rerun when the git commit changes.
108+
// First, find the `HEAD` file. This should work even with worktrees.
109+
let output = Command::new("git").args(["rev-parse", "--git-dir"]).output().ok()?;
110+
let stdout = output.status.success().then_some(output.stdout)?;
111+
let git_dir = PathBuf::from(String::from_utf8(stdout).ok()?.trim());
112+
// Read the HEAD file to determine the name of the current ref.
113+
let git_head_file = git_dir.join("HEAD");
114+
let git_head_ref = String::from_utf8(std::fs::read(&git_head_file).ok()?).ok()?;
115+
let git_head_ref = git_head_ref.strip_prefix("ref:")?.trim();
116+
// Find the directory that stores the ref files.
117+
// Refs *can* be packed, but the checked-out branch is not packed,
118+
// so we should always be able to find this file.
119+
let output = Command::new("git")
120+
.args(["rev-parse", "--git-common-dir"])
106121
.output()
107122
.ok()?;
123+
let stdout = output.status.success().then_some(output.stdout)?;
124+
let git_common_dir = PathBuf::from(String::from_utf8(stdout).ok()?.trim());
125+
// Determine the file where the target of that ref is stored.
126+
let git_head_ref_file = git_common_dir.join(git_head_ref);
127+
if !git_head_ref_file.exists() {
128+
// Something went wrong.
129+
return None;
130+
}
131+
132+
println!("cargo::rerun-if-changed={}", git_head_file.display());
133+
println!("cargo::rerun-if-changed={}", git_head_ref_file.display());
134+
Some(())
135+
}
136+
137+
#[must_use]
138+
pub fn get_commit_hash() -> Option<String> {
139+
let output = Command::new("git").args(["rev-parse", "HEAD"]).output().ok()?;
108140
let mut stdout = output.status.success().then_some(output.stdout)?;
109141
stdout.truncate(10);
110142
String::from_utf8(stdout).ok()
111143
}
112144

113145
#[must_use]
114146
pub fn get_commit_date() -> Option<String> {
115-
let output = std::process::Command::new("git")
147+
let output = Command::new("git")
116148
.args(["log", "-1", "--date=short", "--pretty=format:%cd"])
117149
.output()
118150
.ok()?;

0 commit comments

Comments
 (0)