|
| 1 | +use std::path::PathBuf; |
| 2 | +use std::process::Command; |
1 | 3 | use std::str; |
2 | 4 |
|
3 | 5 | /// This macro creates the version string during compilation from the |
@@ -32,6 +34,7 @@ macro_rules! get_version_info { |
32 | 34 | #[macro_export] |
33 | 35 | macro_rules! setup_version_info { |
34 | 36 | () => {{ |
| 37 | + let _ = $crate::rerun_if_git_changes(); |
35 | 38 | println!( |
36 | 39 | "cargo:rustc-env=GIT_HASH={}", |
37 | 40 | $crate::get_commit_hash().unwrap_or_default() |
@@ -100,19 +103,48 @@ impl std::fmt::Debug for VersionInfo { |
100 | 103 | } |
101 | 104 |
|
102 | 105 | #[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"]) |
106 | 121 | .output() |
107 | 122 | .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()?; |
108 | 140 | let mut stdout = output.status.success().then_some(output.stdout)?; |
109 | 141 | stdout.truncate(10); |
110 | 142 | String::from_utf8(stdout).ok() |
111 | 143 | } |
112 | 144 |
|
113 | 145 | #[must_use] |
114 | 146 | pub fn get_commit_date() -> Option<String> { |
115 | | - let output = std::process::Command::new("git") |
| 147 | + let output = Command::new("git") |
116 | 148 | .args(["log", "-1", "--date=short", "--pretty=format:%cd"]) |
117 | 149 | .output() |
118 | 150 | .ok()?; |
|
0 commit comments