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( )
@@ -41,6 +44,7 @@ macro_rules! setup_version_info {
4144 $crate:: get_commit_date( ) . unwrap_or_default( )
4245 ) ;
4346 println!( "cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}" , $crate:: get_channel( ) ) ;
47+ panic!( )
4448 } } ;
4549}
4650
@@ -99,20 +103,40 @@ impl std::fmt::Debug for VersionInfo {
99103 }
100104}
101105
106+ #[ must_use]
107+ pub fn rerun_if_git_changes ( ) -> Option < ( ) > {
108+ // Make sure we get rerun when the git commit changes.
109+ // First, find the `HEAD` file. This should work even with worktrees.
110+ let output = Command :: new ( "git" ) . args ( [ "rev-parse" , "--git-dir" ] ) . output ( ) . ok ( ) ?;
111+ let stdout = output. status . success ( ) . then_some ( output. stdout ) ?;
112+ let git_dir = PathBuf :: from ( String :: from_utf8 ( stdout) . ok ( ) ?. trim ( ) ) ;
113+ // Read the HEAD file to determine the name of the current ref.
114+ let git_head_file = git_dir. join ( "HEAD" ) ;
115+ let git_head_ref = String :: from_utf8 ( std:: fs:: read ( & git_head_file) . ok ( ) ?) . ok ( ) ?;
116+ let git_head_ref = git_head_ref. strip_prefix ( "ref:" ) ?. trim ( ) ;
117+ // Find the directory that stores the ref files.
118+ let output = Command :: new ( "git" ) . args ( [ "rev-parse" , "--git-common-dir" ] ) . output ( ) . ok ( ) ?;
119+ let stdout = output. status . success ( ) . then_some ( output. stdout ) ?;
120+ let git_common_dir = PathBuf :: from ( String :: from_utf8 ( stdout) . ok ( ) ?. trim ( ) ) ;
121+ // Determine the file where the target of that ref is stored.
122+ let git_head_ref_file = git_common_dir. join ( git_head_ref) ;
123+
124+ println ! ( "cargo::rerun-if-changed={}" , git_head_file. display( ) ) ;
125+ println ! ( "cargo::rerun-if-changed={}" , git_head_ref_file. display( ) ) ;
126+ Some ( ( ) )
127+ }
128+
102129#[ must_use]
103130pub fn get_commit_hash ( ) -> Option < String > {
104- let output = std:: process:: Command :: new ( "git" )
105- . args ( [ "rev-parse" , "HEAD" ] )
106- . output ( )
107- . ok ( ) ?;
131+ let output = Command :: new ( "git" ) . args ( [ "rev-parse" , "HEAD" ] ) . output ( ) . ok ( ) ?;
108132 let mut stdout = output. status . success ( ) . then_some ( output. stdout ) ?;
109133 stdout. truncate ( 10 ) ;
110134 String :: from_utf8 ( stdout) . ok ( )
111135}
112136
113137#[ must_use]
114138pub fn get_commit_date ( ) -> Option < String > {
115- let output = std :: process :: Command :: new ( "git" )
139+ let output = Command :: new ( "git" )
116140 . args ( [ "log" , "-1" , "--date=short" , "--pretty=format:%cd" ] )
117141 . output ( )
118142 . ok ( ) ?;
0 commit comments