@@ -19,7 +19,8 @@ use std::fs;
19
19
use std:: io;
20
20
use std:: path:: { Path , PathBuf } ;
21
21
use std:: process:: Command ;
22
- use std:: time:: Instant ;
22
+ use std:: time:: { SystemTime , Instant } ;
23
+ use std:: fmt:: Display ;
23
24
24
25
use filetime:: { self , FileTime } ;
25
26
@@ -324,3 +325,86 @@ pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> {
324
325
}
325
326
}
326
327
}
328
+
329
+ /// An RAII structure that indicates all output until this instance is dropped
330
+ /// is part of the same group. On Travis CI, these output will be folded by
331
+ /// default. This reduces visibility of unnecessary logs, allowing developers to
332
+ /// quickly identify the error.
333
+ pub struct OutputFolder < D : Display > {
334
+ name : D ,
335
+ start_time : SystemTime , // we need SystemTime to get the UNIX timestamp.
336
+ }
337
+
338
+ impl < D : Display > OutputFolder < D > {
339
+ /// Creates a new output folder with the given group name.
340
+ pub fn new ( name : D ) -> OutputFolder < D > {
341
+ print ! ( "travis_fold:start:{0}\n travis_time:start:{0}\r \x1b [0K" , name) ;
342
+ OutputFolder {
343
+ name,
344
+ start_time : SystemTime :: now ( ) ,
345
+ }
346
+ }
347
+ }
348
+
349
+ impl < D : Display > Drop for OutputFolder < D > {
350
+ fn drop ( & mut self ) {
351
+ use std:: time:: * ;
352
+ use std:: u64;
353
+
354
+ fn to_nanos ( duration : Result < Duration , SystemTimeError > ) -> u64 {
355
+ match duration {
356
+ Ok ( d) => d. as_secs ( ) * 1_000_000_000 + d. subsec_nanos ( ) as u64 ,
357
+ Err ( _) => u64:: MAX ,
358
+ }
359
+ }
360
+
361
+ let end_time = SystemTime :: now ( ) ;
362
+ let duration = end_time. duration_since ( self . start_time ) ;
363
+ let start = self . start_time . duration_since ( UNIX_EPOCH ) ;
364
+ let finish = end_time. duration_since ( UNIX_EPOCH ) ;
365
+ println ! (
366
+ "travis_fold:end:{0}\n travis_time:end:{0}:start={1},finish={2},duration={3}\r \x1b [0K" ,
367
+ self . name,
368
+ to_nanos( start) ,
369
+ to_nanos( finish) ,
370
+ to_nanos( duration)
371
+ ) ;
372
+ }
373
+ }
374
+
375
+ /// The CI environment rustbuild is running in. This mainly affects how the logs
376
+ /// are printed.
377
+ #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
378
+ pub enum CiEnv {
379
+ /// Not a CI environment.
380
+ None ,
381
+ /// The Travis CI environment, for Linux (including Docker) and macOS builds.
382
+ Travis ,
383
+ /// The AppVeyor environment, for Windows builds.
384
+ AppVeyor ,
385
+ }
386
+
387
+ impl CiEnv {
388
+ /// Obtains the current CI environment.
389
+ pub fn current ( ) -> CiEnv {
390
+ if env:: var ( "TRAVIS" ) . ok ( ) . map_or ( false , |e| & * e == "true" ) {
391
+ CiEnv :: Travis
392
+ } else if env:: var ( "APPVEYOR" ) . ok ( ) . map_or ( false , |e| & * e == "True" ) {
393
+ CiEnv :: AppVeyor
394
+ } else {
395
+ CiEnv :: None
396
+ }
397
+ }
398
+
399
+ /// If in a CI environment, forces the command to run with colors.
400
+ pub fn force_coloring_in_ci ( self , cmd : & mut Command ) {
401
+ if self != CiEnv :: None {
402
+ // Due to use of stamp/docker, the output stream of rustbuild is not
403
+ // a TTY in CI, so coloring is by-default turned off.
404
+ // The explicit `TERM=xterm` environment is needed for
405
+ // `--color always` to actually work. This env var was lost when
406
+ // compiling through the Makefile. Very strange.
407
+ cmd. env ( "TERM" , "xterm" ) . args ( & [ "--color" , "always" ] ) ;
408
+ }
409
+ }
410
+ }
0 commit comments