@@ -403,27 +403,58 @@ private static function hasColorSupport()
403
403
return false ;
404
404
}
405
405
406
- if (' Hyper ' === getenv ( ' TERM_PROGRAM ' )) {
406
+ if (! self :: isTty ( )) {
407
407
return true ;
408
408
}
409
409
410
- if (\DIRECTORY_SEPARATOR === '\\' ) {
411
- return (\function_exists ('sapi_windows_vt100_support ' )
412
- && sapi_windows_vt100_support (\STDOUT ))
413
- || false !== getenv ('ANSICON ' )
414
- || 'ON ' === getenv ('ConEmuANSI ' )
415
- || 'xterm ' === getenv ('TERM ' );
410
+ if ('\\' === \DIRECTORY_SEPARATOR
411
+ && \function_exists ('sapi_windows_vt100_support ' )
412
+ && @sapi_windows_vt100_support (\STDOUT )
413
+ ) {
414
+ return true ;
416
415
}
417
416
417
+ if ('Hyper ' === getenv ('TERM_PROGRAM ' )
418
+ || false !== getenv ('COLORTERM ' )
419
+ || false !== getenv ('ANSICON ' )
420
+ || 'ON ' === getenv ('ConEmuANSI ' )
421
+ ) {
422
+ return true ;
423
+ }
424
+
425
+ if ('dumb ' === $ term = (string ) getenv ('TERM ' )) {
426
+ return false ;
427
+ }
428
+
429
+ // See https://github.com/chalk/supports-color/blob/d4f413efaf8da045c5ab440ed418ef02dbb28bf1/index.js#L157
430
+ return preg_match ('/^((screen|xterm|vt100|vt220|putty|rxvt|ansi|cygwin|linux).*)|(.*-256(color)?(-bce)?)$/ ' , $ term );
431
+ }
432
+
433
+ /**
434
+ * Checks if the stream is a TTY, i.e; whether the output stream is connected to a terminal.
435
+ *
436
+ * Reference: Composer\Util\Platform::isTty
437
+ * https://github.com/composer/composer
438
+ */
439
+ private static function isTty (): bool
440
+ {
441
+ // Detect msysgit/mingw and assume this is a tty because detection
442
+ // does not work correctly, see https://github.com/composer/composer/issues/9690
443
+ if (\in_array (strtoupper ((string ) getenv ('MSYSTEM ' )), ['MINGW32 ' , 'MINGW64 ' ], true )) {
444
+ return true ;
445
+ }
446
+
447
+ // Modern cross-platform function, includes the fstat fallback so if it is present we trust it
418
448
if (\function_exists ('stream_isatty ' )) {
419
449
return @stream_isatty (\STDOUT );
420
450
}
421
451
422
- if (\function_exists ('posix_isatty ' )) {
423
- return @posix_isatty (\STDOUT );
452
+ // Only trusting this if it is positive, otherwise prefer fstat fallback.
453
+ if (\function_exists ('posix_isatty ' ) && @posix_isatty (\STDOUT )) {
454
+ return true ;
424
455
}
425
456
426
- $ stat = fstat (\STDOUT );
457
+ $ stat = @ fstat (\STDOUT );
427
458
428
459
// Check if formatted mode is S_IFCHR
429
460
return $ stat ? 0020000 === ($ stat ['mode ' ] & 0170000 ) : false ;
0 commit comments