1+ use std:: path:: PathBuf ;
2+ use std:: process:: Command ;
13use 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]
3335macro_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( )
@@ -99,25 +102,55 @@ impl std::fmt::Debug for VersionInfo {
99102 }
100103}
101104
105+ fn get_output ( cmd : & str , args : & [ & str ] ) -> Option < String > {
106+ let output = Command :: new ( cmd) . args ( args) . output ( ) . ok ( ) ?;
107+ let mut stdout = output. status . success ( ) . then_some ( output. stdout ) ?;
108+ // Remove trailing newlines.
109+ while stdout. last ( ) . copied ( ) == Some ( '\n' as u8 ) {
110+ stdout. pop ( ) ;
111+ }
112+ String :: from_utf8 ( stdout) . ok ( )
113+ }
114+
115+ #[ must_use]
116+ pub fn rerun_if_git_changes ( ) -> Option < ( ) > {
117+ // Make sure we get rerun when the git commit changes.
118+ // We want to watch two files: HEAD, which tracks which branch we are on,
119+ // and the file for that branch that tracks which commit is is on.
120+
121+ // First, find the `HEAD` file. This should work even with worktrees.
122+ let git_dir = PathBuf :: from ( get_output ( "git" , & [ "rev-parse" , "--git-dir" ] ) ?) ;
123+ let git_head_file = git_dir. join ( "HEAD" ) ;
124+ if git_head_file. exists ( ) {
125+ println ! ( "cargo::rerun-if-changed={}" , git_head_file. display( ) ) ;
126+ }
127+
128+ // Determine the name of the current ref.
129+ // This will quit if HEAD is detached.
130+ let git_head_ref = get_output ( "git" , & [ "symbolic-ref" , "-q" , "HEAD" ] ) ?;
131+ // Find the directory that stores the ref files.
132+ // Refs *can* be packed, but the checked-out branch is not packed,
133+ // so we should always be able to find this file.
134+ let git_common_dir = PathBuf :: from ( get_output ( "git" , & [ "rev-parse" , "--git-common-dir" ] ) ?) ;
135+ // Determine the file where the target of that ref is stored.
136+ let git_head_ref_file = git_common_dir. join ( git_head_ref) ;
137+ if git_head_ref_file. exists ( ) {
138+ println ! ( "cargo::rerun-if-changed={}" , git_head_ref_file. display( ) ) ;
139+ }
140+
141+ Some ( ( ) )
142+ }
143+
102144#[ must_use]
103145pub fn get_commit_hash ( ) -> Option < String > {
104- let output = std:: process:: Command :: new ( "git" )
105- . args ( [ "rev-parse" , "HEAD" ] )
106- . output ( )
107- . ok ( ) ?;
108- let mut stdout = output. status . success ( ) . then_some ( output. stdout ) ?;
146+ let mut stdout = get_output ( "git" , & [ "rev-parse" , "HEAD" ] ) ?;
109147 stdout. truncate ( 10 ) ;
110- String :: from_utf8 ( stdout) . ok ( )
148+ Some ( stdout)
111149}
112150
113151#[ must_use]
114152pub fn get_commit_date ( ) -> Option < String > {
115- let output = std:: process:: Command :: new ( "git" )
116- . args ( [ "log" , "-1" , "--date=short" , "--pretty=format:%cd" ] )
117- . output ( )
118- . ok ( ) ?;
119- let stdout = output. status . success ( ) . then_some ( output. stdout ) ?;
120- String :: from_utf8 ( stdout) . ok ( )
153+ get_output ( "git" , & [ "log" , "-1" , "--date=short" , "--pretty=format:%cd" ] )
121154}
122155
123156#[ must_use]
@@ -127,15 +160,11 @@ pub fn get_channel() -> String {
127160 }
128161
129162 // if that failed, try to ask rustc -V, do some parsing and find out
130- if let Ok ( output) = std:: process:: Command :: new ( "rustc" ) . arg ( "-V" ) . output ( ) {
131- if output. status . success ( ) {
132- if let Ok ( rustc_output) = str:: from_utf8 ( & output. stdout ) {
133- if rustc_output. contains ( "beta" ) {
134- return String :: from ( "beta" ) ;
135- } else if rustc_output. contains ( "stable" ) {
136- return String :: from ( "stable" ) ;
137- }
138- }
163+ if let Some ( rustc_output) = get_output ( "rustc" , & [ "-V" ] ) {
164+ if rustc_output. contains ( "beta" ) {
165+ return String :: from ( "beta" ) ;
166+ } else if rustc_output. contains ( "stable" ) {
167+ return String :: from ( "stable" ) ;
139168 }
140169 }
141170
0 commit comments