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,24 +103,52 @@ 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
- . output ( )
107
- . ok ( ) ?;
106
+ fn get_output ( cmd : & str , args : & [ & str ] ) -> Option < String > {
107
+ let output = Command :: new ( cmd) . args ( args) . output ( ) . ok ( ) ?;
108
108
let mut stdout = output. status . success ( ) . then_some ( output. stdout ) ?;
109
- stdout. truncate ( 10 ) ;
109
+ // Remove trailing newlines.
110
+ while stdout. last ( ) . copied ( ) == Some ( b'\n' ) {
111
+ stdout. pop ( ) ;
112
+ }
110
113
String :: from_utf8 ( stdout) . ok ( )
111
114
}
112
115
116
+ #[ must_use]
117
+ pub fn rerun_if_git_changes ( ) -> Option < ( ) > {
118
+ // Make sure we get rerun when the git commit changes.
119
+ // We want to watch two files: HEAD, which tracks which branch we are on,
120
+ // and the file for that branch that tracks which commit is is on.
121
+
122
+ // First, find the `HEAD` file. This should work even with worktrees.
123
+ let git_head_file = PathBuf :: from ( get_output ( "git" , & [ "rev-parse" , "--git-path" , "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
+ // Ask git where this ref is stored.
132
+ let git_head_ref_file = PathBuf :: from ( get_output ( "git" , & [ "rev-parse" , "--git-path" , & git_head_ref] ) ?) ;
133
+ // If this ref is packed, the file does not exist. However, the checked-out branch is never (?)
134
+ // packed, so we should always be able to find this file.
135
+ if git_head_ref_file. exists ( ) {
136
+ println ! ( "cargo::rerun-if-changed={}" , git_head_ref_file. display( ) ) ;
137
+ }
138
+
139
+ Some ( ( ) )
140
+ }
141
+
142
+ #[ must_use]
143
+ pub fn get_commit_hash ( ) -> Option < String > {
144
+ let mut stdout = get_output ( "git" , & [ "rev-parse" , "HEAD" ] ) ?;
145
+ stdout. truncate ( 10 ) ;
146
+ Some ( stdout)
147
+ }
148
+
113
149
#[ must_use]
114
150
pub 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 ( )
151
+ get_output ( "git" , & [ "log" , "-1" , "--date=short" , "--pretty=format:%cd" ] )
121
152
}
122
153
123
154
#[ must_use]
@@ -127,15 +158,11 @@ pub fn get_channel() -> String {
127
158
}
128
159
129
160
// 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
- }
161
+ if let Some ( rustc_output) = get_output ( "rustc" , & [ "-V" ] ) {
162
+ if rustc_output. contains ( "beta" ) {
163
+ return String :: from ( "beta" ) ;
164
+ } else if rustc_output. contains ( "stable" ) {
165
+ return String :: from ( "stable" ) ;
139
166
}
140
167
}
141
168
@@ -151,7 +178,7 @@ mod test {
151
178
fn test_struct_local ( ) {
152
179
let vi = get_version_info ! ( ) ;
153
180
assert_eq ! ( vi. major, 0 ) ;
154
- assert_eq ! ( vi. minor, 3 ) ;
181
+ assert_eq ! ( vi. minor, 4 ) ;
155
182
assert_eq ! ( vi. patch, 0 ) ;
156
183
assert_eq ! ( vi. crate_name, "rustc_tools_util" ) ;
157
184
// hard to make positive tests for these since they will always change
@@ -162,7 +189,7 @@ mod test {
162
189
#[ test]
163
190
fn test_display_local ( ) {
164
191
let vi = get_version_info ! ( ) ;
165
- assert_eq ! ( vi. to_string( ) , "rustc_tools_util 0.3 .0" ) ;
192
+ assert_eq ! ( vi. to_string( ) , "rustc_tools_util 0.4 .0" ) ;
166
193
}
167
194
168
195
#[ test]
@@ -171,7 +198,7 @@ mod test {
171
198
let s = format ! ( "{vi:?}" ) ;
172
199
assert_eq ! (
173
200
s,
174
- "VersionInfo { crate_name: \" rustc_tools_util\" , major: 0, minor: 3 , patch: 0 }"
201
+ "VersionInfo { crate_name: \" rustc_tools_util\" , major: 0, minor: 4 , patch: 0 }"
175
202
) ;
176
203
}
177
204
}
0 commit comments