16
16
use std:: env;
17
17
use std:: ffi:: OsString ;
18
18
use std:: fs;
19
- use std:: io;
19
+ use std:: io:: { self , Write } ;
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
23
24
24
use filetime:: { self , FileTime } ;
25
25
@@ -324,3 +324,102 @@ pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> {
324
324
}
325
325
}
326
326
}
327
+
328
+ /// An RAII structure that indicates all output until this instance is dropped
329
+ /// is part of the same group.
330
+ ///
331
+ /// On Travis CI, these output will be folded by default, together with the
332
+ /// elapsed time in this block. This reduces noise from unnecessary logs,
333
+ /// allowing developers to quickly identify the error.
334
+ ///
335
+ /// Travis CI supports folding by printing `travis_fold:start:<name>` and
336
+ /// `travis_fold:end:<name>` around the block. Time elapsed is recognized
337
+ /// similarly with `travis_time:[start|end]:<name>`. These are undocumented, but
338
+ /// can easily be deduced from source code of the [Travis build commands].
339
+ ///
340
+ /// [Travis build commands]:
341
+ /// https://github.com/travis-ci/travis-build/blob/f603c0089/lib/travis/build/templates/header.sh
342
+ pub struct OutputFolder {
343
+ name : String ,
344
+ start_time : SystemTime , // we need SystemTime to get the UNIX timestamp.
345
+ }
346
+
347
+ impl OutputFolder {
348
+ /// Creates a new output folder with the given group name.
349
+ pub fn new ( name : String ) -> OutputFolder {
350
+ // "\r" moves the cursor to the beginning of the line, and "\x1b[0K" is
351
+ // the ANSI escape code to clear from the cursor to end of line.
352
+ // Travis seems to have trouble when _not_ using "\r\x1b[0K", that will
353
+ // randomly put lines to the top of the webpage.
354
+ print ! ( "travis_fold:start:{0}\r \x1b [0Ktravis_time:start:{0}\r \x1b [0K" , name) ;
355
+ OutputFolder {
356
+ name,
357
+ start_time : SystemTime :: now ( ) ,
358
+ }
359
+ }
360
+ }
361
+
362
+ impl Drop for OutputFolder {
363
+ fn drop ( & mut self ) {
364
+ use std:: time:: * ;
365
+ use std:: u64;
366
+
367
+ fn to_nanos ( duration : Result < Duration , SystemTimeError > ) -> u64 {
368
+ match duration {
369
+ Ok ( d) => d. as_secs ( ) * 1_000_000_000 + d. subsec_nanos ( ) as u64 ,
370
+ Err ( _) => u64:: MAX ,
371
+ }
372
+ }
373
+
374
+ let end_time = SystemTime :: now ( ) ;
375
+ let duration = end_time. duration_since ( self . start_time ) ;
376
+ let start = self . start_time . duration_since ( UNIX_EPOCH ) ;
377
+ let finish = end_time. duration_since ( UNIX_EPOCH ) ;
378
+ println ! (
379
+ "travis_fold:end:{0}\r \x1b [0K\n \
380
+ travis_time:end:{0}:start={1},finish={2},duration={3}\r \x1b [0K",
381
+ self . name,
382
+ to_nanos( start) ,
383
+ to_nanos( finish) ,
384
+ to_nanos( duration)
385
+ ) ;
386
+ io:: stdout ( ) . flush ( ) . unwrap ( ) ;
387
+ }
388
+ }
389
+
390
+ /// The CI environment rustbuild is running in. This mainly affects how the logs
391
+ /// are printed.
392
+ #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
393
+ pub enum CiEnv {
394
+ /// Not a CI environment.
395
+ None ,
396
+ /// The Travis CI environment, for Linux (including Docker) and macOS builds.
397
+ Travis ,
398
+ /// The AppVeyor environment, for Windows builds.
399
+ AppVeyor ,
400
+ }
401
+
402
+ impl CiEnv {
403
+ /// Obtains the current CI environment.
404
+ pub fn current ( ) -> CiEnv {
405
+ if env:: var ( "TRAVIS" ) . ok ( ) . map_or ( false , |e| & * e == "true" ) {
406
+ CiEnv :: Travis
407
+ } else if env:: var ( "APPVEYOR" ) . ok ( ) . map_or ( false , |e| & * e == "True" ) {
408
+ CiEnv :: AppVeyor
409
+ } else {
410
+ CiEnv :: None
411
+ }
412
+ }
413
+
414
+ /// If in a CI environment, forces the command to run with colors.
415
+ pub fn force_coloring_in_ci ( self , cmd : & mut Command ) {
416
+ if self != CiEnv :: None {
417
+ // Due to use of stamp/docker, the output stream of rustbuild is not
418
+ // a TTY in CI, so coloring is by-default turned off.
419
+ // The explicit `TERM=xterm` environment is needed for
420
+ // `--color always` to actually work. This env var was lost when
421
+ // compiling through the Makefile. Very strange.
422
+ cmd. env ( "TERM" , "xterm" ) . args ( & [ "--color" , "always" ] ) ;
423
+ }
424
+ }
425
+ }
0 commit comments