@@ -95,6 +95,10 @@ protected function hasColorSupport()
95
95
return false ;
96
96
}
97
97
98
+ if (!$ this ->isTty ()) {
99
+ return false ;
100
+ }
101
+
98
102
if (\DIRECTORY_SEPARATOR === '\\'
99
103
&& \function_exists ('sapi_windows_vt100_support ' )
100
104
&& @sapi_windows_vt100_support ($ this ->stream )
@@ -105,7 +109,36 @@ protected function hasColorSupport()
105
109
return 'Hyper ' === getenv ('TERM_PROGRAM ' )
106
110
|| false !== getenv ('ANSICON ' )
107
111
|| 'ON ' === getenv ('ConEmuANSI ' )
108
- || str_starts_with ((string ) getenv ('TERM ' ), 'xterm ' )
109
- || stream_isatty ($ this ->stream );
112
+ || str_starts_with ((string ) getenv ('TERM ' ), 'xterm ' );
113
+ }
114
+
115
+ /**
116
+ * Checks if the stream is a TTY, i.e; whether the output stream is connected to a terminal.
117
+ *
118
+ * Reference: Composer\Util\Platform::isTty
119
+ * https://github.com/composer/composer
120
+ */
121
+ private function isTty (): bool
122
+ {
123
+ // Detect msysgit/mingw and assume this is a tty because detection
124
+ // does not work correctly, see https://github.com/composer/composer/issues/9690
125
+ if (\in_array (strtoupper ((string ) getenv ('MSYSTEM ' )), ['MINGW32 ' , 'MINGW64 ' ], true )) {
126
+ return true ;
127
+ }
128
+
129
+ // Modern cross-platform function, includes the fstat fallback so if it is present we trust it
130
+ if (\function_exists ('stream_isatty ' )) {
131
+ return stream_isatty ($ this ->stream );
132
+ }
133
+
134
+ // Only trusting this if it is positive, otherwise prefer fstat fallback.
135
+ if (\function_exists ('posix_isatty ' ) && posix_isatty ($ this ->stream )) {
136
+ return true ;
137
+ }
138
+
139
+ $ stat = @fstat ($ this ->stream );
140
+
141
+ // Check if formatted mode is S_IFCHR
142
+ return $ stat ? 0020000 === ($ stat ['mode ' ] & 0170000 ) : false ;
110
143
}
111
144
}
0 commit comments