@@ -10,34 +10,67 @@ 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 )
21
+
22
+ args = args . to_a . map ( &:to_s )
23
+ # TODO: Remove __skip__ once we have open3 RBS definitions.
24
+ __skip__ =
25
+ if @verbose || !$stdout. tty?
26
+ kwargs [ :exception ] = true
27
+ if env
28
+ Kernel . system ( env , *args , **kwargs )
29
+ else
30
+ Kernel . system ( *args , **kwargs )
31
+ end
29
32
else
30
- Kernel . system ( *args . to_a . map ( &:to_s ) , **kwargs )
33
+ printer = StatusPrinter . new
34
+ block =
35
+ proc do |stdin , stdout , stderr , wait_thr |
36
+ mux = Mutex . new
37
+ out = String . new
38
+ err = String . new
39
+ readers =
40
+ [
41
+ [ stdout , :stdout , out ] ,
42
+ [ stderr , :stderr , err ]
43
+ ] . map do |io , name , str |
44
+ reader =
45
+ Thread . new do
46
+ while ( line = io . gets )
47
+ mux . synchronize do
48
+ printer . send ( name , line )
49
+ str << line
50
+ end
51
+ end
52
+ end
53
+ reader . report_on_exception = false
54
+ reader
55
+ end
56
+
57
+ readers . each ( &:join )
58
+
59
+ [ out , err , wait_thr . value ]
60
+ end
61
+ begin
62
+ if env
63
+ Open3 . popen3 ( env , *args , **kwargs , &block )
64
+ else
65
+ Open3 . popen3 ( *args , **kwargs , &block )
66
+ end
67
+ ensure
68
+ printer . done
69
+ end
31
70
end
32
- ensure
33
- out . close if out_pipe
34
- end
35
71
rescue => e
36
- if out_pipe
37
- # Print the output of the failed command
38
- puts out_pipe [ 0 ] . read
39
- end
40
72
$stdout. flush
73
+ $stderr. puts "Try running with `rake --verbose` for more complete output."
41
74
raise e
42
75
end
43
76
@@ -58,9 +91,7 @@ def begin_section(klass, name, note)
58
91
59
92
def end_section ( klass , name )
60
93
took = Time . now - @start_times [ [ klass , name ] ]
61
- if @github_actions_markup
62
- puts "::endgroup::"
63
- end
94
+ puts "::endgroup::" if @github_actions_markup
64
95
puts "\e [1;36m==>\e [0m \e [1m#{ klass } (#{ name } ) -- done in #{ took . round ( 2 ) } s\e [0m"
65
96
end
66
97
@@ -98,4 +129,46 @@ def _print_command(args, env)
98
129
print args . map { |arg | Shellwords . escape ( arg . to_s ) } . join ( " " ) + "\n "
99
130
end
100
131
end
132
+
133
+ # Human readable status printer for the build.
134
+ class StatusPrinter
135
+ def initialize
136
+ @mutex = Mutex . new
137
+ @counter = 0
138
+ @indicators = "|/-\\ "
139
+ end
140
+
141
+ def stdout ( message )
142
+ require "io/console"
143
+ @mutex . synchronize do
144
+ $stdout. print "\e [K"
145
+ first_line = message . lines ( chomp : true ) . first || ""
146
+
147
+ # Make sure we don't line-wrap the output
148
+ size =
149
+ __skip__ =
150
+ IO . respond_to? ( :console_size ) ? IO . console_size : IO . console . winsize
151
+ terminal_width = size [ 1 ] . to_i . nonzero? || 80
152
+ width_limit = terminal_width / 2 - 3
153
+
154
+ if first_line . length > width_limit
155
+ first_line = ( first_line [ 0 ..width_limit - 5 ] || "" ) + "..."
156
+ end
157
+ indicator = @indicators [ @counter ] || " "
158
+ to_print = " " + indicator + " " + first_line
159
+ $stdout. print to_print
160
+ $stdout. print "\e [1A\n "
161
+ @counter += 1
162
+ @counter = 0 if @counter >= @indicators . length
163
+ end
164
+ end
165
+
166
+ def stderr ( message )
167
+ @mutex . synchronize { $stdout. print message }
168
+ end
169
+
170
+ def done
171
+ @mutex . synchronize { $stdout. print "\e [K" }
172
+ end
173
+ end
101
174
end
0 commit comments