1616use std:: env;
1717use std:: ffi:: OsString ;
1818use std:: fs;
19- use std:: io;
19+ use std:: io:: { self , Write } ;
2020use std:: path:: { Path , PathBuf } ;
2121use std:: process:: Command ;
22- use std:: time:: Instant ;
22+ use std:: time:: { SystemTime , Instant } ;
2323
2424use filetime:: { self , FileTime } ;
2525
@@ -324,3 +324,102 @@ pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> {
324324 }
325325 }
326326}
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