@@ -19,7 +19,8 @@ use std::fs;
1919use std:: io;
2020use std:: path:: { Path , PathBuf } ;
2121use std:: process:: Command ;
22- use std:: time:: Instant ;
22+ use std:: time:: { SystemTime , Instant } ;
23+ use std:: fmt:: Display ;
2324
2425use filetime:: { self , FileTime } ;
2526
@@ -324,3 +325,86 @@ pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> {
324325 }
325326 }
326327}
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