@@ -10,34 +10,53 @@ def initialize(verbose: false)
10
10
@github_actions_markup = ENV [ "ENABLE_GITHUB_ACTIONS_MARKUP" ] != nil
11
11
end
12
12
13
- def system ( *args , chdir : nil , out : nil , env : nil )
13
+ def system ( *args , chdir : nil , env : nil )
14
+ require "open3"
15
+
14
16
_print_command ( args , env )
15
17
16
- if @verbose
17
- out ||= $stdout
18
- else
19
- # Capture stdout by default
20
- out_pipe = IO . pipe
21
- out = out_pipe [ 1 ]
22
- end
23
18
# @type var kwargs: Hash[Symbol, untyped]
24
- kwargs = { exception : true , out : out }
19
+ kwargs = { }
25
20
kwargs [ :chdir ] = chdir if chdir
26
- begin
27
- if env
28
- Kernel . system ( env , *args . to_a . map ( &:to_s ) , **kwargs )
29
- else
30
- Kernel . system ( *args . to_a . map ( &:to_s ) , **kwargs )
21
+
22
+ args = args . to_a . map ( &:to_s )
23
+ # TODO: Remove __skip__ once we have open3 RBS definitions.
24
+ __skip__ = if @verbose || !$stdout. tty?
25
+ kwargs [ :exception ] = true
26
+ env ? Kernel . system ( env , *args , **kwargs ) : Kernel . system ( *args , **kwargs )
27
+ else
28
+ printer = StatusPrinter . new
29
+ block = proc do |stdin , stdout , stderr , wait_thr |
30
+ mux = Mutex . new
31
+ out = String . new
32
+ err = String . new
33
+ readers = [ [ stdout , :stdout , out ] , [ stderr , :stderr , err ] ] . map do |io , name , str |
34
+ reader = Thread . new {
35
+ while ( line = io . gets )
36
+ mux . synchronize {
37
+ printer . send ( name , line )
38
+ str << line
39
+ }
40
+ end
41
+ }
42
+ reader . report_on_exception = false
43
+ reader
44
+ end
45
+
46
+ readers . each ( &:join )
47
+
48
+ [ out , err , wait_thr . value ]
49
+ end
50
+ begin
51
+ env ? Open3 . popen3 ( env , *args , **kwargs , &block ) : Open3 . popen3 ( *args , **kwargs , &block )
52
+ ensure
53
+ printer . done
31
54
end
32
- ensure
33
- out . close if out_pipe
34
55
end
56
+
35
57
rescue => e
36
- if out_pipe
37
- # Print the output of the failed command
38
- puts out_pipe [ 0 ] . read
39
- end
40
58
$stdout. flush
59
+ $stderr. puts "Try running with `rake --verbose` for more complete output."
41
60
raise e
42
61
end
43
62
@@ -58,9 +77,7 @@ def begin_section(klass, name, note)
58
77
59
78
def end_section ( klass , name )
60
79
took = Time . now - @start_times [ [ klass , name ] ]
61
- if @github_actions_markup
62
- puts "::endgroup::"
63
- end
80
+ puts "::endgroup::" if @github_actions_markup
64
81
puts "\e [1;36m==>\e [0m \e [1m#{ klass } (#{ name } ) -- done in #{ took . round ( 2 ) } s\e [0m"
65
82
end
66
83
@@ -98,4 +115,48 @@ def _print_command(args, env)
98
115
print args . map { |arg | Shellwords . escape ( arg . to_s ) } . join ( " " ) + "\n "
99
116
end
100
117
end
118
+
119
+ # Human readable status printer for the build.
120
+ class StatusPrinter
121
+ def initialize
122
+ @mutex = Mutex . new
123
+ @counter = 0
124
+ @indicators = "|/-\\ "
125
+ end
126
+
127
+ def stdout ( message )
128
+ require "io/console"
129
+ @mutex . synchronize {
130
+ $stdout. print "\e [K"
131
+ first_line = message . lines ( chomp : true ) . first || ""
132
+
133
+ # Make sure we don't line-wrap the output
134
+ size = __skip__ = IO . respond_to? ( :console_size ) ? IO . console_size : IO . console . winsize
135
+ terminal_width = size [ 1 ] . to_i . nonzero? || 80
136
+ width_limit = terminal_width / 2 - 3
137
+
138
+ if first_line . length > width_limit
139
+ first_line = ( first_line [ 0 ..width_limit - 5 ] || "" ) + "..."
140
+ end
141
+ indicator = @indicators [ @counter ] || " "
142
+ to_print = " " + indicator + " " + first_line
143
+ $stdout. print to_print
144
+ $stdout. print "\e [1A\n "
145
+ @counter += 1
146
+ @counter = 0 if @counter >= @indicators . length
147
+ }
148
+ end
149
+
150
+ def stderr ( message )
151
+ @mutex . synchronize {
152
+ $stdout. print message
153
+ }
154
+ end
155
+
156
+ def done
157
+ @mutex . synchronize {
158
+ $stdout. print "\e [K"
159
+ }
160
+ end
161
+ end
101
162
end
0 commit comments