@@ -113,11 +113,12 @@ use std::os;
113
113
use std:: path:: { Path , PathBuf } ;
114
114
use std:: process:: { Command , Output } ;
115
115
use std:: str;
116
- use std:: time:: Duration ;
116
+ use std:: time:: { self , Duration } ;
117
117
use std:: usize;
118
118
119
119
use cargo;
120
120
use cargo:: util:: { CargoResult , ProcessBuilder , ProcessError , Rustc } ;
121
+ use filetime;
121
122
use serde_json:: { self , Value } ;
122
123
use url:: Url ;
123
124
@@ -279,8 +280,19 @@ impl ProjectBuilder {
279
280
self . _file ( Path :: new ( "Cargo.toml" ) , & basic_manifest ( "foo" , "0.0.1" ) )
280
281
}
281
282
283
+ let past = time:: SystemTime :: now ( ) - Duration :: new ( 1 , 0 ) ;
284
+ let ftime = filetime:: FileTime :: from_system_time ( past) ;
285
+
282
286
for file in self . files . iter ( ) {
283
287
file. mk ( ) ;
288
+ if is_coarse_mtime ( ) {
289
+ // Place the entire project 1 second in the past to ensure
290
+ // that if cargo is called multiple times, the 2nd call will
291
+ // see targets as "fresh". Without this, if cargo finishes in
292
+ // under 1 second, the second call will see the mtime of
293
+ // source == mtime of output and consider it dirty.
294
+ filetime:: set_file_times ( & file. path , ftime, ftime) . unwrap ( ) ;
295
+ }
284
296
}
285
297
286
298
for symlink in self . symlinks . iter ( ) {
@@ -1510,3 +1522,11 @@ pub fn git_process(s: &str) -> ProcessBuilder {
1510
1522
pub fn sleep_ms ( ms : u64 ) {
1511
1523
:: std:: thread:: sleep ( Duration :: from_millis ( ms) ) ;
1512
1524
}
1525
+
1526
+ /// Returns true if the local filesystem has low-resolution mtimes.
1527
+ pub fn is_coarse_mtime ( ) -> bool {
1528
+ // This should actually be a test that $CARGO_TARGET_DIR is on an HFS
1529
+ // filesystem, (or any filesystem with low-resolution mtimes). However,
1530
+ // that's tricky to detect, so for now just deal with CI.
1531
+ cfg ! ( target_os = "macos" ) && env:: var ( "CI" ) . is_ok ( )
1532
+ }
0 commit comments