autobuild 1.17.0 → 1.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +107 -0
- data/.travis.yml +3 -2
- data/Gemfile +2 -1
- data/Rakefile +1 -4
- data/autobuild.gemspec +18 -13
- data/bin/autobuild +4 -3
- data/lib/autobuild.rb +4 -5
- data/lib/autobuild/build_logfile.rb +6 -4
- data/lib/autobuild/config.rb +104 -41
- data/lib/autobuild/configurable.rb +32 -18
- data/lib/autobuild/environment.rb +126 -120
- data/lib/autobuild/exceptions.rb +48 -31
- data/lib/autobuild/import/archive.rb +134 -82
- data/lib/autobuild/import/cvs.rb +28 -24
- data/lib/autobuild/import/darcs.rb +13 -16
- data/lib/autobuild/import/git-lfs.rb +37 -30
- data/lib/autobuild/import/git.rb +246 -182
- data/lib/autobuild/import/hg.rb +23 -18
- data/lib/autobuild/import/svn.rb +48 -29
- data/lib/autobuild/importer.rb +534 -499
- data/lib/autobuild/mail_reporter.rb +77 -77
- data/lib/autobuild/package.rb +200 -122
- data/lib/autobuild/packages/autotools.rb +47 -42
- data/lib/autobuild/packages/cmake.rb +77 -65
- data/lib/autobuild/packages/dummy.rb +9 -8
- data/lib/autobuild/packages/genom.rb +1 -1
- data/lib/autobuild/packages/gnumake.rb +74 -31
- data/lib/autobuild/packages/import.rb +2 -6
- data/lib/autobuild/packages/orogen.rb +32 -31
- data/lib/autobuild/packages/pkgconfig.rb +2 -2
- data/lib/autobuild/packages/python.rb +12 -8
- data/lib/autobuild/packages/ruby.rb +22 -17
- data/lib/autobuild/parallel.rb +50 -46
- data/lib/autobuild/pkgconfig.rb +25 -13
- data/lib/autobuild/progress_display.rb +149 -64
- data/lib/autobuild/rake_task_extension.rb +12 -7
- data/lib/autobuild/reporting.rb +51 -26
- data/lib/autobuild/subcommand.rb +72 -65
- data/lib/autobuild/test.rb +9 -7
- data/lib/autobuild/test_utility.rb +12 -10
- data/lib/autobuild/timestamps.rb +28 -23
- data/lib/autobuild/tools.rb +17 -16
- data/lib/autobuild/utility.rb +67 -23
- data/lib/autobuild/version.rb +1 -1
- metadata +53 -37
@@ -1,19 +1,24 @@
|
|
1
1
|
module Autobuild
|
2
2
|
module RakeTaskExtension
|
3
3
|
def already_invoked?
|
4
|
-
|
4
|
+
@already_invoked
|
5
5
|
end
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
attr_writer :already_invoked
|
8
|
+
|
9
|
+
def disabled?
|
10
|
+
@disabled
|
11
|
+
end
|
12
|
+
|
13
|
+
def disabled!
|
14
|
+
disable
|
9
15
|
end
|
10
16
|
|
11
|
-
def disable
|
12
|
-
@
|
13
|
-
def self.needed?; false end
|
17
|
+
def disable
|
18
|
+
@disabled = true
|
14
19
|
end
|
15
20
|
end
|
16
21
|
end
|
17
|
-
class Rake::Task
|
22
|
+
class Rake::Task # rubocop:disable Style/ClassAndModuleChildren
|
18
23
|
include Autobuild::RakeTaskExtension
|
19
24
|
end
|
data/lib/autobuild/reporting.rb
CHANGED
@@ -16,6 +16,7 @@ def color=(flag)
|
|
16
16
|
def color?
|
17
17
|
@colorizer.enabled?
|
18
18
|
end
|
19
|
+
|
19
20
|
def color(message, *style)
|
20
21
|
@colorizer.decorate(message, *style)
|
21
22
|
end
|
@@ -31,6 +32,7 @@ class << self
|
|
31
32
|
def silent?
|
32
33
|
@display.silent?
|
33
34
|
end
|
35
|
+
|
34
36
|
def silent=(flag)
|
35
37
|
@display.silent = flag
|
36
38
|
end
|
@@ -45,10 +47,23 @@ def self.progress_display_enabled?
|
|
45
47
|
@display.progress_enabled?
|
46
48
|
end
|
47
49
|
|
50
|
+
def self.progress_display_synchronize(&block)
|
51
|
+
@display.synchronize(&block)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @deprecated use {progress_display_mode=} instead
|
48
55
|
def self.progress_display_enabled=(value)
|
49
56
|
@display.progress_enabled = value
|
50
57
|
end
|
51
58
|
|
59
|
+
def self.progress_display_mode=(value)
|
60
|
+
@display.progress_mode = value
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.progress_display_period=(value)
|
64
|
+
@display.progress_period = value
|
65
|
+
end
|
66
|
+
|
52
67
|
def self.message(*args, **options)
|
53
68
|
@display.message(*args, **options)
|
54
69
|
end
|
@@ -80,7 +95,7 @@ def self.progress_done(key, display_last = true, message: nil)
|
|
80
95
|
#
|
81
96
|
# It does not use a logging framework like Log4r, but it should ;-)
|
82
97
|
module Reporting
|
83
|
-
|
98
|
+
@reporters = Array.new
|
84
99
|
|
85
100
|
## Run a block and report known exception
|
86
101
|
# If an exception is fatal, the program is terminated using exit()
|
@@ -89,18 +104,22 @@ def self.report(on_package_failures: default_report_on_package_failures)
|
|
89
104
|
rescue Interrupt => e
|
90
105
|
interrupted = e
|
91
106
|
rescue Autobuild::Exception => e
|
92
|
-
return report_finish_on_error([e],
|
107
|
+
return report_finish_on_error([e],
|
108
|
+
on_package_failures: on_package_failures,
|
109
|
+
interrupted_by: interrupted)
|
93
110
|
end
|
94
111
|
|
95
112
|
# If ignore_erorrs is true, check if some packages have failed
|
96
113
|
# on the way. If so, raise an exception to inform the user about
|
97
114
|
# it
|
98
115
|
errors = []
|
99
|
-
Autobuild::Package.each do |
|
116
|
+
Autobuild::Package.each do |_name, pkg|
|
100
117
|
errors.concat(pkg.failures)
|
101
118
|
end
|
102
119
|
|
103
|
-
report_finish_on_error(errors,
|
120
|
+
report_finish_on_error(errors,
|
121
|
+
on_package_failures: on_package_failures,
|
122
|
+
interrupted_by: interrupted)
|
104
123
|
end
|
105
124
|
|
106
125
|
# @api private
|
@@ -121,15 +140,18 @@ def self.default_report_on_package_failures
|
|
121
140
|
#
|
122
141
|
# @param [Symbol] on_package_failures how does the reporting should behave.
|
123
142
|
#
|
124
|
-
def self.report_finish_on_error(errors,
|
125
|
-
|
143
|
+
def self.report_finish_on_error(errors,
|
144
|
+
on_package_failures: default_report_on_package_failures, interrupted_by: nil)
|
145
|
+
if (not_package_error = errors.find { |e| !e.respond_to?(:fatal?) })
|
126
146
|
raise not_package_error
|
127
147
|
end
|
128
|
-
|
148
|
+
|
149
|
+
unless %i[raise report_silent exit_silent].include?(on_package_failures)
|
129
150
|
errors.each { |e| error(e) }
|
130
151
|
end
|
152
|
+
|
131
153
|
fatal = errors.any?(&:fatal?)
|
132
|
-
|
154
|
+
unless fatal
|
133
155
|
if interrupted_by
|
134
156
|
raise interrupted_by
|
135
157
|
else
|
@@ -138,30 +160,29 @@ def self.report_finish_on_error(errors, on_package_failures: default_report_on_p
|
|
138
160
|
end
|
139
161
|
|
140
162
|
if on_package_failures == :raise
|
141
|
-
if interrupted_by
|
142
|
-
raise interrupted_by
|
143
|
-
end
|
163
|
+
raise interrupted_by if interrupted_by
|
144
164
|
|
145
165
|
e = if errors.size == 1 then errors.first
|
146
|
-
|
147
|
-
|
166
|
+
else CompositeException.new(errors)
|
167
|
+
end
|
148
168
|
raise e
|
149
|
-
elsif [
|
169
|
+
elsif %i[report_silent report].include?(on_package_failures)
|
150
170
|
if interrupted_by
|
151
171
|
raise interrupted_by
|
152
172
|
else
|
153
173
|
return errors
|
154
174
|
end
|
155
|
-
elsif [
|
175
|
+
elsif %i[exit exit_silent].include?(on_package_failures)
|
156
176
|
exit 1
|
157
177
|
else
|
158
|
-
raise ArgumentError, "unexpected value for on_package_failures:
|
178
|
+
raise ArgumentError, "unexpected value for on_package_failures: "\
|
179
|
+
"#{on_package_failures}"
|
159
180
|
end
|
160
181
|
end
|
161
182
|
|
162
183
|
## Reports a successful build to the user
|
163
184
|
def self.success
|
164
|
-
each_reporter
|
185
|
+
each_reporter(&:success)
|
165
186
|
end
|
166
187
|
|
167
188
|
## Reports that the build failed to the user
|
@@ -171,19 +192,19 @@ def self.error(error)
|
|
171
192
|
|
172
193
|
## Add a new reporter
|
173
194
|
def self.<<(reporter)
|
174
|
-
|
195
|
+
@reporters << reporter
|
175
196
|
end
|
176
197
|
|
177
198
|
def self.remove(reporter)
|
178
|
-
|
199
|
+
@reporters.delete(reporter)
|
179
200
|
end
|
180
201
|
|
181
202
|
def self.clear_reporters
|
182
|
-
|
203
|
+
@reporters.clear
|
183
204
|
end
|
184
205
|
|
185
206
|
def self.each_reporter(&iter)
|
186
|
-
|
207
|
+
@reporters.each(&iter)
|
187
208
|
end
|
188
209
|
|
189
210
|
## Iterate on all log files
|
@@ -195,6 +216,7 @@ def self.each_log(&block)
|
|
195
216
|
## Base class for reporters
|
196
217
|
class Reporter
|
197
218
|
def error(error); end
|
219
|
+
|
198
220
|
def success; end
|
199
221
|
end
|
200
222
|
|
@@ -203,11 +225,10 @@ class StdoutReporter < Reporter
|
|
203
225
|
def error(error)
|
204
226
|
STDERR.puts "Build failed: #{error}"
|
205
227
|
end
|
228
|
+
|
206
229
|
def success
|
207
230
|
puts "Build finished successfully at #{Time.now}"
|
208
|
-
if Autobuild.post_success_message
|
209
|
-
puts Autobuild.post_success_message
|
210
|
-
end
|
231
|
+
puts Autobuild.post_success_message if Autobuild.post_success_message
|
211
232
|
end
|
212
233
|
end
|
213
234
|
|
@@ -216,12 +237,16 @@ def success
|
|
216
237
|
[1_000_000.0, "M"],
|
217
238
|
[1_000.0, "k"],
|
218
239
|
[1.0, ""]
|
219
|
-
]
|
240
|
+
].freeze
|
220
241
|
|
221
242
|
def self.human_readable_size(size)
|
222
243
|
HUMAN_READABLE_SIZES.each do |scale, name|
|
223
244
|
scaled_size = (size / scale)
|
224
|
-
|
245
|
+
if scaled_size > 1
|
246
|
+
return format("%3.1<scaled>f%<scale_name>s",
|
247
|
+
scaled: scaled_size,
|
248
|
+
scale_name: name)
|
249
|
+
end
|
225
250
|
end
|
226
251
|
end
|
227
252
|
end
|
data/lib/autobuild/subcommand.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require 'autobuild/exceptions'
|
3
3
|
require 'autobuild/reporting'
|
4
4
|
require 'fcntl'
|
5
|
+
require 'English'
|
5
6
|
|
6
7
|
module Autobuild
|
7
8
|
@logfiles = Set.new
|
@@ -24,9 +25,11 @@ def self.registered_logfile?(logfile)
|
|
24
25
|
def self.statistics
|
25
26
|
@statistics
|
26
27
|
end
|
28
|
+
|
27
29
|
def self.reset_statistics
|
28
30
|
@statistics = Hash.new
|
29
31
|
end
|
32
|
+
|
30
33
|
def self.add_stat(package, phase, duration)
|
31
34
|
if !@statistics[package]
|
32
35
|
@statistics[package] = { phase => duration }
|
@@ -36,6 +39,7 @@ def self.add_stat(package, phase, duration)
|
|
36
39
|
@statistics[package][phase] += duration
|
37
40
|
end
|
38
41
|
end
|
42
|
+
|
39
43
|
reset_statistics
|
40
44
|
|
41
45
|
@parallel_build_level = nil
|
@@ -52,9 +56,8 @@ class << self
|
|
52
56
|
def displayed_error_line_count=(value)
|
53
57
|
@displayed_error_line_count = validate_displayed_error_line_count(value)
|
54
58
|
end
|
55
|
-
|
56
|
-
|
57
|
-
end
|
59
|
+
|
60
|
+
attr_reader :displayed_error_line_count
|
58
61
|
|
59
62
|
# Returns the number of processes that can run in parallel during the
|
60
63
|
# build. This is a system-wide value that can be overriden in a
|
@@ -78,13 +81,13 @@ def parallel_build_level
|
|
78
81
|
|
79
82
|
# Returns the number of CPUs present on this system
|
80
83
|
def self.autodetect_processor_count
|
81
|
-
if @processor_count
|
82
|
-
return @processor_count
|
83
|
-
end
|
84
|
+
return @processor_count if @processor_count
|
84
85
|
|
85
86
|
if File.file?('/proc/cpuinfo')
|
86
87
|
cpuinfo = File.readlines('/proc/cpuinfo')
|
87
|
-
physical_ids
|
88
|
+
physical_ids = []
|
89
|
+
core_count = []
|
90
|
+
processor_ids = []
|
88
91
|
cpuinfo.each do |line|
|
89
92
|
case line
|
90
93
|
when /^processor\s+:\s+(\d+)$/
|
@@ -99,7 +102,10 @@ def self.autodetect_processor_count
|
|
99
102
|
# Try to count the number of physical cores, not the number of
|
100
103
|
# logical ones. If the info is not available, fallback to the
|
101
104
|
# logical count
|
102
|
-
|
105
|
+
has_consistent_info =
|
106
|
+
(physical_ids.size == core_count.size) &&
|
107
|
+
(physical_ids.size == processor_ids.size)
|
108
|
+
if has_consistent_info
|
103
109
|
info = Array.new
|
104
110
|
while (id = physical_ids.shift)
|
105
111
|
info[id] = core_count.shift
|
@@ -112,18 +118,17 @@ def self.autodetect_processor_count
|
|
112
118
|
result = Open3.popen3("sysctl", "-n", "hw.ncpu") do |_, io, _|
|
113
119
|
io.read
|
114
120
|
end
|
115
|
-
|
116
|
-
@processor_count = Integer(result.chomp.strip)
|
117
|
-
end
|
121
|
+
@processor_count = Integer(result.chomp.strip) unless result.empty?
|
118
122
|
end
|
119
123
|
|
120
124
|
# The format of the cpuinfo file is ... let's say not very standardized.
|
121
125
|
# If the cpuinfo detection fails, inform the user and set it to 1
|
122
|
-
|
126
|
+
unless @processor_count
|
123
127
|
# Hug... What kind of system is it ?
|
124
128
|
Autobuild.message "INFO: cannot autodetect the number of CPUs on this sytem"
|
125
129
|
Autobuild.message "INFO: turning parallel builds off"
|
126
|
-
Autobuild.message "INFO: you can manually set the number of parallel build
|
130
|
+
Autobuild.message "INFO: you can manually set the number of parallel build "\
|
131
|
+
"processes to N"
|
127
132
|
Autobuild.message "INFO: (and therefore turn this message off)"
|
128
133
|
Autobuild.message "INFO: with"
|
129
134
|
Autobuild.message " Autobuild.parallel_build_level = N"
|
@@ -135,20 +140,24 @@ def self.autodetect_processor_count
|
|
135
140
|
|
136
141
|
def self.validate_displayed_error_line_count(lines)
|
137
142
|
if lines == 'ALL'
|
138
|
-
|
143
|
+
Float::INFINITY
|
139
144
|
elsif lines.to_i > 0
|
140
|
-
|
145
|
+
lines.to_i
|
146
|
+
else
|
147
|
+
raise ConfigException.new, 'Autobuild.displayed_error_line_count can only "\
|
148
|
+
"be a positive integer or \'ALL\''
|
141
149
|
end
|
142
|
-
raise ConfigException.new, 'Autobuild.displayed_error_line_count can only be a positive integer or \'ALL\''
|
143
150
|
end
|
144
151
|
end
|
145
152
|
|
146
|
-
|
147
|
-
|
148
|
-
class Failed < Exception
|
149
|
-
def retry?; @retry end
|
153
|
+
module Autobuild::Subprocess # rubocop:disable Style/ClassAndModuleChildren
|
154
|
+
class Failed < RuntimeError
|
150
155
|
attr_reader :status
|
151
156
|
|
157
|
+
def retry?
|
158
|
+
@retry
|
159
|
+
end
|
160
|
+
|
152
161
|
def initialize(status, do_retry)
|
153
162
|
@status = status
|
154
163
|
@retry = do_retry
|
@@ -206,7 +215,11 @@ def self.run(target, phase, *command)
|
|
206
215
|
STDOUT.sync = true
|
207
216
|
|
208
217
|
input_streams = []
|
209
|
-
options =
|
218
|
+
options = {
|
219
|
+
retry: false, encoding: 'BINARY',
|
220
|
+
env: ENV.to_hash, env_inherit: true
|
221
|
+
}
|
222
|
+
|
210
223
|
if command.last.kind_of?(Hash)
|
211
224
|
options = command.pop
|
212
225
|
options = Kernel.validate_options options,
|
@@ -216,19 +229,15 @@ def self.run(target, phase, *command)
|
|
216
229
|
env_inherit: true,
|
217
230
|
encoding: 'BINARY'
|
218
231
|
|
219
|
-
if options[:input]
|
220
|
-
|
221
|
-
end
|
222
|
-
if options[:input_streams]
|
223
|
-
input_streams += options[:input_streams]
|
224
|
-
end
|
232
|
+
input_streams << File.open(options[:input]) if options[:input]
|
233
|
+
input_streams.concat(options[:input_streams]) if options[:input_streams]
|
225
234
|
end
|
226
235
|
|
227
236
|
start_time = Time.now
|
228
237
|
|
229
238
|
# Filter nil and empty? in command
|
230
|
-
command.reject!
|
231
|
-
command.collect!
|
239
|
+
command.reject! { |o| o.nil? || (o.respond_to?(:empty?) && o.empty?) }
|
240
|
+
command.collect!(&:to_s)
|
232
241
|
|
233
242
|
if target.respond_to?(:name)
|
234
243
|
target_name = target.name
|
@@ -246,13 +255,15 @@ def self.run(target, phase, *command)
|
|
246
255
|
options[:working_directory] ||= target.working_directory
|
247
256
|
end
|
248
257
|
|
249
|
-
logname = File.join(logdir, "#{target_name.gsub(/[:]/,'_')}
|
250
|
-
|
258
|
+
logname = File.join(logdir, "#{target_name.gsub(/[:]/, '_')}-"\
|
259
|
+
"#{phase.to_s.gsub(/[:]/, '_')}.log")
|
260
|
+
unless File.directory?(File.dirname(logname))
|
251
261
|
FileUtils.mkdir_p File.dirname(logname)
|
252
262
|
end
|
253
263
|
|
254
264
|
if Autobuild.verbose
|
255
|
-
Autobuild.message "#{target_name}: running #{command.join(
|
265
|
+
Autobuild.message "#{target_name}: running #{command.join(' ')}\n"\
|
266
|
+
" (output goes to #{logname})"
|
256
267
|
end
|
257
268
|
|
258
269
|
open_flag = if Autobuild.keep_oldlogs then 'a'
|
@@ -267,32 +278,28 @@ def self.run(target, phase, *command)
|
|
267
278
|
env = options[:env].dup
|
268
279
|
if options[:env_inherit]
|
269
280
|
ENV.each do |k, v|
|
270
|
-
|
271
|
-
env[k] = v
|
272
|
-
end
|
281
|
+
env[k] = v unless env.key?(k)
|
273
282
|
end
|
274
283
|
end
|
275
284
|
|
276
285
|
status = File.open(logname, open_flag) do |logfile|
|
277
|
-
if Autobuild.keep_oldlogs
|
278
|
-
logfile.puts
|
279
|
-
end
|
286
|
+
logfile.puts if Autobuild.keep_oldlogs
|
280
287
|
logfile.puts
|
281
288
|
logfile.puts "#{Time.now}: running"
|
282
|
-
logfile.puts " #{command.join(
|
289
|
+
logfile.puts " #{command.join(' ')}"
|
283
290
|
logfile.puts "with environment:"
|
284
291
|
env.keys.sort.each do |key|
|
285
|
-
if value = env[key]
|
292
|
+
if (value = env[key])
|
286
293
|
logfile.puts " '#{key}'='#{value}'"
|
287
294
|
end
|
288
295
|
end
|
289
296
|
logfile.puts
|
290
297
|
logfile.puts "#{Time.now}: running"
|
291
|
-
logfile.puts " #{command.join(
|
298
|
+
logfile.puts " #{command.join(' ')}"
|
292
299
|
logfile.flush
|
293
300
|
logfile.sync = true
|
294
301
|
|
295
|
-
|
302
|
+
unless input_streams.empty?
|
296
303
|
pread, pwrite = IO.pipe # to feed subprocess stdin
|
297
304
|
end
|
298
305
|
|
@@ -304,22 +311,19 @@ def self.run(target, phase, *command)
|
|
304
311
|
|
305
312
|
if Autobuild.windows?
|
306
313
|
Dir.chdir(options[:working_directory]) do
|
307
|
-
|
308
|
-
raise Failed.new(
|
314
|
+
unless system(*command)
|
315
|
+
raise Failed.new($CHILD_STATUS.exitstatus, nil),
|
309
316
|
"'#{command.join(' ')}' returned status #{status.exitstatus}"
|
310
317
|
end
|
311
318
|
end
|
312
|
-
return
|
319
|
+
return # rubocop:disable Lint/NonLocalExitFromIterator
|
313
320
|
end
|
314
321
|
|
315
322
|
cwrite.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
316
323
|
|
317
324
|
pid = fork do
|
318
325
|
begin
|
319
|
-
|
320
|
-
Dir.chdir(options[:working_directory])
|
321
|
-
end
|
322
|
-
logfile.puts "in directory #{Dir.pwd}"
|
326
|
+
logfile.puts "in directory #{options[:working_directory] || Dir.pwd}"
|
323
327
|
|
324
328
|
cwrite.sync = true
|
325
329
|
if Autobuild.nice
|
@@ -330,19 +334,23 @@ def self.run(target, phase, *command)
|
|
330
334
|
$stderr.reopen(outwrite.dup)
|
331
335
|
$stdout.reopen(outwrite.dup)
|
332
336
|
|
333
|
-
|
337
|
+
unless input_streams.empty?
|
334
338
|
pwrite.close
|
335
339
|
$stdin.reopen(pread)
|
336
340
|
end
|
337
341
|
|
338
|
-
exec(env, *command,
|
342
|
+
exec(env, *command,
|
343
|
+
chdir: options[:working_directory] || Dir.pwd,
|
344
|
+
close_others: false)
|
339
345
|
rescue Errno::ENOENT
|
340
346
|
cwrite.write([CONTROL_COMMAND_NOT_FOUND].pack('I'))
|
341
347
|
exit(100)
|
342
348
|
rescue Interrupt
|
343
349
|
cwrite.write([CONTROL_INTERRUPT].pack('I'))
|
344
350
|
exit(100)
|
345
|
-
rescue ::Exception
|
351
|
+
rescue ::Exception => e
|
352
|
+
STDERR.puts e
|
353
|
+
STDERR.puts e.backtrace.join("\n ")
|
346
354
|
cwrite.write([CONTROL_UNEXPECTED].pack('I'))
|
347
355
|
exit(100)
|
348
356
|
end
|
@@ -351,12 +359,14 @@ def self.run(target, phase, *command)
|
|
351
359
|
readbuffer = StringIO.new
|
352
360
|
|
353
361
|
# Feed the input
|
354
|
-
|
362
|
+
unless input_streams.empty?
|
355
363
|
pread.close
|
356
364
|
begin
|
357
365
|
input_streams.each do |instream|
|
358
366
|
instream.each_line do |line|
|
359
|
-
|
367
|
+
while IO.select([outread], nil, nil, 0)
|
368
|
+
readbuffer.write(outread.readpartial(128))
|
369
|
+
end
|
360
370
|
pwrite.write(line)
|
361
371
|
end
|
362
372
|
end
|
@@ -385,15 +395,13 @@ def self.run(target, phase, *command)
|
|
385
395
|
end
|
386
396
|
|
387
397
|
transparent_prefix = "#{target_name}:#{phase}: "
|
388
|
-
if target_type
|
389
|
-
transparent_prefix = "#{target_type}:#{transparent_prefix}"
|
390
|
-
end
|
398
|
+
transparent_prefix = "#{target_type}:#{transparent_prefix}" if target_type
|
391
399
|
|
392
400
|
# If the caller asked for process output, provide it to him
|
393
401
|
# line-by-line.
|
394
402
|
outwrite.close
|
395
403
|
|
396
|
-
|
404
|
+
unless input_streams.empty?
|
397
405
|
readbuffer.write(outread.read)
|
398
406
|
readbuffer.seek(0)
|
399
407
|
outread.close
|
@@ -428,6 +436,7 @@ def self.run(target, phase, *command)
|
|
428
436
|
if status.termsig == 2 # SIGINT == 2
|
429
437
|
raise Interrupt, "subcommand #{command.join(' ')} interrupted"
|
430
438
|
end
|
439
|
+
|
431
440
|
if status.termsig
|
432
441
|
raise Failed.new(status.exitstatus, nil),
|
433
442
|
"'#{command.join(' ')}' terminated by signal #{status.termsig}"
|
@@ -441,21 +450,19 @@ def self.run(target, phase, *command)
|
|
441
450
|
Autobuild.add_stat(target, phase, duration)
|
442
451
|
FileUtils.mkdir_p(Autobuild.logdir)
|
443
452
|
File.open(File.join(Autobuild.logdir, "stats.log"), 'a') do |io|
|
444
|
-
|
453
|
+
formatted_msec = format('%.03i', start_time.tv_usec / 1000)
|
454
|
+
formatted_time = "#{start_time.strftime('%F %H:%M:%S')}.#{formatted_msec}"
|
445
455
|
io.puts "#{formatted_time} #{target_name} #{phase} #{duration}"
|
446
456
|
end
|
447
|
-
if target.respond_to?(:add_stat)
|
448
|
-
target.add_stat(phase, duration)
|
449
|
-
end
|
457
|
+
target.add_stat(phase, duration) if target.respond_to?(:add_stat)
|
450
458
|
subcommand_output
|
451
|
-
|
452
459
|
rescue Failed => e
|
453
|
-
error = Autobuild::SubcommandFailed.new(target, command.join(" "),
|
460
|
+
error = Autobuild::SubcommandFailed.new(target, command.join(" "),
|
461
|
+
logname, e.status, subcommand_output)
|
454
462
|
error.retry = if e.retry?.nil? then options[:retry]
|
455
463
|
else e.retry?
|
456
464
|
end
|
457
465
|
error.phase = phase
|
458
466
|
raise error, e.message
|
459
467
|
end
|
460
|
-
|
461
468
|
end
|