autobuild 1.8.3 → 1.9.0.b1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Manifest.txt +16 -7
- data/Rakefile +2 -0
- data/lib/autobuild/config.rb +21 -6
- data/lib/autobuild/configurable.rb +2 -2
- data/lib/autobuild/environment.rb +52 -27
- data/lib/autobuild/exceptions.rb +48 -22
- data/lib/autobuild/import/archive.rb +37 -16
- data/lib/autobuild/import/cvs.rb +26 -28
- data/lib/autobuild/import/darcs.rb +9 -8
- data/lib/autobuild/import/git.rb +324 -217
- data/lib/autobuild/import/hg.rb +6 -9
- data/lib/autobuild/import/svn.rb +190 -47
- data/lib/autobuild/importer.rb +80 -35
- data/lib/autobuild/package.rb +16 -35
- data/lib/autobuild/packages/autotools.rb +8 -8
- data/lib/autobuild/packages/cmake.rb +18 -12
- data/lib/autobuild/packages/genom.rb +1 -1
- data/lib/autobuild/packages/gnumake.rb +11 -12
- data/lib/autobuild/packages/orogen.rb +1 -1
- data/lib/autobuild/packages/ruby.rb +9 -5
- data/lib/autobuild/reporting.rb +10 -6
- data/lib/autobuild/subcommand.rb +110 -50
- data/lib/autobuild/test.rb +104 -0
- data/lib/autobuild/timestamps.rb +3 -3
- data/lib/autobuild/tools.rb +1 -1
- data/lib/autobuild/utility.rb +22 -10
- data/lib/autobuild/version.rb +1 -1
- data/test/data/gitrepo-with-extra-commit-and-tag.tar +0 -0
- data/test/data/gitrepo.tar +0 -0
- data/test/data/gitrepo/test +0 -0
- data/test/data/gitrepo/test2 +0 -0
- data/test/data/gitrepo/test3 +0 -0
- data/test/data/svnroot.tar +0 -0
- data/test/import/test_cvs.rb +51 -0
- data/test/import/test_git.rb +364 -0
- data/test/import/test_svn.rb +144 -0
- data/test/import/test_tar.rb +76 -0
- data/test/suite.rb +7 -0
- data/test/test_config.rb +1 -5
- data/test/test_environment.rb +88 -0
- data/test/test_reporting.rb +2 -14
- data/test/test_subcommand.rb +7 -22
- metadata +17 -14
- data/test/test_import_cvs.rb +0 -59
- data/test/test_import_svn.rb +0 -56
- data/test/test_import_tar.rb +0 -83
- data/test/tools.rb +0 -44
data/lib/autobuild/package.rb
CHANGED
@@ -127,6 +127,9 @@ module Autobuild
|
|
127
127
|
def updated?; !!@updated end
|
128
128
|
|
129
129
|
def initialize(spec = Hash.new)
|
130
|
+
@srcdir = @importdir = @logdir = nil
|
131
|
+
@update = nil
|
132
|
+
@failed = nil
|
130
133
|
@dependencies = Array.new
|
131
134
|
@provides = Array.new
|
132
135
|
@parallel_build_level = nil
|
@@ -187,7 +190,7 @@ module Autobuild
|
|
187
190
|
# target files so that all the build phases of this package gets
|
188
191
|
# retriggered. However, it should not clean the build products.
|
189
192
|
def prepare_for_forced_build
|
190
|
-
if File.
|
193
|
+
if File.exist?(installstamp)
|
191
194
|
FileUtils.rm_f installstamp
|
192
195
|
end
|
193
196
|
end
|
@@ -197,7 +200,7 @@ module Autobuild
|
|
197
200
|
def prepare_for_rebuild
|
198
201
|
prepare_for_forced_build
|
199
202
|
|
200
|
-
if File.
|
203
|
+
if File.exist?(installstamp)
|
201
204
|
FileUtils.rm_f installstamp
|
202
205
|
end
|
203
206
|
end
|
@@ -258,17 +261,22 @@ module Autobuild
|
|
258
261
|
end
|
259
262
|
|
260
263
|
# Call the importer if there is one. Autodetection of "provides" should
|
261
|
-
# be done there as well.
|
262
|
-
#
|
263
|
-
|
264
|
+
# be done there as well.
|
265
|
+
#
|
266
|
+
# (see Importer#import)
|
267
|
+
def import(options = Hash.new)
|
268
|
+
if !options.respond_to?(:to_hash)
|
269
|
+
options = Hash[only_local: options]
|
270
|
+
end
|
271
|
+
|
264
272
|
if @importer
|
265
|
-
@importer.import(self,
|
266
|
-
elsif
|
273
|
+
@importer.import(self, options)
|
274
|
+
elsif update?
|
267
275
|
message "%s: no importer defined, doing nothing"
|
268
276
|
end
|
269
277
|
|
270
278
|
# Add the dependencies declared in spec
|
271
|
-
depends_on
|
279
|
+
depends_on(*@spec_dependencies) if @spec_dependencies
|
272
280
|
update_environment
|
273
281
|
end
|
274
282
|
|
@@ -404,33 +412,6 @@ module Autobuild
|
|
404
412
|
task
|
405
413
|
end
|
406
414
|
|
407
|
-
module TaskExtension
|
408
|
-
attr_accessor :package
|
409
|
-
end
|
410
|
-
|
411
|
-
def source_tree(*args, &block)
|
412
|
-
task = Autobuild.source_tree(*args, &block)
|
413
|
-
task.extend TaskExtension
|
414
|
-
task.package = self
|
415
|
-
task
|
416
|
-
end
|
417
|
-
|
418
|
-
# Calls Rake to define a file task and then extends it with TaskExtension
|
419
|
-
def file(*args, &block)
|
420
|
-
task = super
|
421
|
-
task.extend TaskExtension
|
422
|
-
task.package = self
|
423
|
-
task
|
424
|
-
end
|
425
|
-
|
426
|
-
# Calls Rake to define a plain task and then extends it with TaskExtension
|
427
|
-
def task(*args, &block)
|
428
|
-
task = super
|
429
|
-
task.extend TaskExtension
|
430
|
-
task.package = self
|
431
|
-
task
|
432
|
-
end
|
433
|
-
|
434
415
|
def doc_dir=(value); doc_utility.source_dir = value end
|
435
416
|
def doc_dir; doc_utility.source_dir end
|
436
417
|
def doc_target_dir=(value); doc_utility.target_dir = value end
|
@@ -102,9 +102,9 @@ module Autobuild
|
|
102
102
|
end
|
103
103
|
|
104
104
|
if !programs.kind_of?(Hash)
|
105
|
-
programs = Array[*programs].inject({}) do |
|
106
|
-
|
107
|
-
|
105
|
+
programs = Array[*programs].inject({}) do |progs, spec|
|
106
|
+
progs[spec.first] = spec.last
|
107
|
+
progs
|
108
108
|
end
|
109
109
|
end
|
110
110
|
programs.each do |name, opt|
|
@@ -168,7 +168,7 @@ module Autobuild
|
|
168
168
|
# If it is not the case, remove it to force reconfiguration
|
169
169
|
configureflags.flatten!
|
170
170
|
force_reconfigure = false
|
171
|
-
if File.
|
171
|
+
if File.exist?(configurestamp)
|
172
172
|
output = IO.popen("#{configurestamp} --version").readlines.grep(/with options/).first.chomp
|
173
173
|
raise "invalid output of config.status --version" unless output =~ /with options "(.*)"$/
|
174
174
|
options = Shellwords.shellwords($1)
|
@@ -224,11 +224,11 @@ module Autobuild
|
|
224
224
|
end
|
225
225
|
using[:aclocal] = using[:autoconf] if using[:aclocal].nil?
|
226
226
|
if using[:automake].nil?
|
227
|
-
using[:automake] = File.
|
227
|
+
using[:automake] = File.exist?(File.join(srcdir, 'Makefile.am'))
|
228
228
|
end
|
229
229
|
|
230
230
|
if using[:libtool].nil?
|
231
|
-
using[:libtool] = File.
|
231
|
+
using[:libtool] = File.exist?(File.join(srcdir, 'ltmain.sh'))
|
232
232
|
end
|
233
233
|
end
|
234
234
|
|
@@ -237,7 +237,7 @@ module Autobuild
|
|
237
237
|
conffile = "#{srcdir}/configure"
|
238
238
|
if confsource
|
239
239
|
file conffile => confsource
|
240
|
-
elsif confext = %w{.ac .in}.find { |ext| File.
|
240
|
+
elsif confext = %w{.ac .in}.find { |ext| File.exist?("#{conffile}#{ext}") }
|
241
241
|
file conffile => "#{conffile}#{confext}"
|
242
242
|
else
|
243
243
|
raise PackageException.new(self, 'prepare'), "neither configure.ac nor configure.in present in #{srcdir}"
|
@@ -247,7 +247,7 @@ module Autobuild
|
|
247
247
|
isolate_errors do
|
248
248
|
in_dir(srcdir) do
|
249
249
|
if using[:autogen].nil?
|
250
|
-
using[:autogen] = %w{autogen autogen.sh}.find { |f| File.
|
250
|
+
using[:autogen] = %w{autogen autogen.sh}.find { |f| File.exist?(File.join(srcdir, f)) }
|
251
251
|
end
|
252
252
|
|
253
253
|
autodetect_needed_stages
|
@@ -76,13 +76,14 @@ module Autobuild
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def define(name, value)
|
79
|
-
@defines[name] =
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
79
|
+
@defines[name] =
|
80
|
+
if value.respond_to?(:to_str)
|
81
|
+
value.to_str
|
82
|
+
elsif value
|
83
|
+
'ON'
|
84
|
+
else
|
85
|
+
'OFF'
|
86
|
+
end
|
86
87
|
end
|
87
88
|
|
88
89
|
DOXYGEN_ACCEPTED_VARIABLES = {
|
@@ -265,13 +266,13 @@ module Autobuild
|
|
265
266
|
# but no Makefile.
|
266
267
|
#
|
267
268
|
# Delete the CMakeCache to force reconfiguration
|
268
|
-
if !File.
|
269
|
+
if !File.exist?( File.join(builddir, 'Makefile') )
|
269
270
|
FileUtils.rm_f cmake_cache
|
270
271
|
end
|
271
272
|
|
272
273
|
doc_utility.source_ref_dir = builddir
|
273
274
|
|
274
|
-
if File.
|
275
|
+
if File.exist?(cmake_cache)
|
275
276
|
all_defines = defines.dup
|
276
277
|
all_defines['CMAKE_INSTALL_PREFIX'] = prefix
|
277
278
|
all_defines['CMAKE_MODULE_PATH'] = "#{CMake.module_path.join(";")}"
|
@@ -361,24 +362,24 @@ module Autobuild
|
|
361
362
|
|
362
363
|
# Do the build in builddir
|
363
364
|
def build
|
365
|
+
current_message = String.new
|
364
366
|
in_dir(builddir) do
|
365
367
|
progress_start "building %s" do
|
366
368
|
if always_reconfigure || !File.file?('Makefile')
|
367
369
|
Subprocess.run(self, 'build', Autobuild.tool(:cmake), '.')
|
368
370
|
end
|
369
371
|
|
370
|
-
current_message = String.new
|
371
372
|
warning_count = 0
|
372
373
|
Autobuild.make_subcommand(self, 'build') do |line|
|
373
374
|
needs_display = false
|
374
375
|
if line =~ /\[\s*(\d+)%\]/
|
375
376
|
progress "building %s (#{Integer($1)}%)"
|
376
|
-
elsif line !~ /^(?:Linking|Scanning|Building|Built)/
|
377
|
+
elsif line !~ /^(?:Generating|Linking|Scanning|Building|Built)/
|
377
378
|
if line =~ /warning/
|
378
379
|
warning_count += 1
|
379
380
|
end
|
380
381
|
if show_make_messages?
|
381
|
-
current_message += line
|
382
|
+
current_message += line + "\n"
|
382
383
|
needs_display = true
|
383
384
|
end
|
384
385
|
end
|
@@ -400,6 +401,11 @@ module Autobuild
|
|
400
401
|
end
|
401
402
|
end
|
402
403
|
Autobuild.touch_stamp(buildstamp)
|
404
|
+
rescue ::Exception
|
405
|
+
current_message.split("\n").each do |l|
|
406
|
+
message "%s: #{l}", :magenta
|
407
|
+
end
|
408
|
+
raise
|
403
409
|
end
|
404
410
|
|
405
411
|
# Install the result in prefix
|
@@ -117,7 +117,7 @@ module Autobuild
|
|
117
117
|
|
118
118
|
# Check that the module has been generated with the same flags
|
119
119
|
genom_mk = "#{srcdir}/autoconf/genom.mk"
|
120
|
-
if File.
|
120
|
+
if File.exist?(genom_mk)
|
121
121
|
contents = File.open(genom_mk).readlines
|
122
122
|
old_file = contents.find { |l| l =~ /^GENFILE/ }.gsub('GENFILE=', '').strip
|
123
123
|
old_flags = Shellwords.shellwords(
|
@@ -18,31 +18,30 @@ module Autobuild
|
|
18
18
|
make_is_gnumake?(path)
|
19
19
|
end
|
20
20
|
|
21
|
-
def self.
|
21
|
+
def self.invoke_make_parallel(pkg, cmd_path = Autobuild.tool(:make))
|
22
22
|
reserved = nil
|
23
|
-
cmd_path = Autobuild.tool(:make)
|
24
|
-
cmd = [cmd_path]
|
25
23
|
if make_has_j_option?(cmd_path) && pkg.parallel_build_level != 1
|
26
24
|
if manager = Autobuild.parallel_task_manager
|
27
25
|
job_server = manager.job_server
|
28
26
|
if !make_has_gnumake_jobserver?(cmd_path) || (pkg.parallel_build_level != Autobuild.parallel_build_level)
|
29
27
|
reserved = pkg.parallel_build_level
|
30
28
|
job_server.get(reserved - 1) # We already have one token taken by autobuild itself
|
31
|
-
|
32
|
-
else
|
33
|
-
cmd << "--jobserver-fds=#{job_server.rio.fileno},#{job_server.wio.fileno}" << "-j"
|
29
|
+
yield("-j#{pkg.parallel_build_level}")
|
34
30
|
end
|
35
|
-
|
36
|
-
cmd << "-j#{pkg.parallel_build_level}"
|
31
|
+
yield("--jobserver-fds=#{job_server.rio.fileno},#{job_server.wio.fileno}", "-j")
|
37
32
|
end
|
33
|
+
yield("-j#{pkg.parallel_build_level}")
|
34
|
+
else yield
|
38
35
|
end
|
39
|
-
|
40
|
-
cmd.concat(options)
|
41
|
-
Subprocess.run(pkg, phase, *cmd, &block)
|
42
|
-
|
43
36
|
ensure
|
44
37
|
if reserved
|
45
38
|
job_server.put(reserved)
|
46
39
|
end
|
47
40
|
end
|
41
|
+
|
42
|
+
def self.make_subcommand(pkg, phase, *options, &block)
|
43
|
+
invoke_make_parallel(pkg, Autobuild.tool(:make)) do |*make_parallel_options|
|
44
|
+
Subprocess.run(pkg, phase, Autobuild.tool(:make), *make_parallel_options, *options, &block)
|
45
|
+
end
|
46
|
+
end
|
48
47
|
end
|
@@ -47,6 +47,14 @@ module Autobuild
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
def invoke_rake(setup_task = rake_setup_task)
|
51
|
+
if setup_task && File.file?(File.join(srcdir, 'Rakefile'))
|
52
|
+
Autobuild::Subprocess.run self, 'post-install',
|
53
|
+
Autobuild.tool_in_path('ruby'), '-S', Autobuild.tool('rake'), setup_task,
|
54
|
+
:working_directory => srcdir
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
50
58
|
def install
|
51
59
|
progress_start "setting up Ruby package %s", :done_message => 'set up Ruby package %s' do
|
52
60
|
Autobuild.update_environment srcdir
|
@@ -57,11 +65,7 @@ module Autobuild
|
|
57
65
|
Autobuild.env_add_path 'RUBYLIB', libdir
|
58
66
|
end
|
59
67
|
|
60
|
-
|
61
|
-
Autobuild::Subprocess.run self, 'post-install',
|
62
|
-
Autobuild.tool_in_path('ruby'), '-S', Autobuild.tool('rake'), rake_setup_task,
|
63
|
-
:working_directory => srcdir
|
64
|
-
end
|
68
|
+
invoke_rake
|
65
69
|
end
|
66
70
|
super
|
67
71
|
end
|
data/lib/autobuild/reporting.rb
CHANGED
@@ -34,13 +34,17 @@ module Autobuild
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def self.display_message(*args)
|
37
|
+
io = STDOUT
|
38
|
+
if args.last.kind_of?(IO)
|
39
|
+
io = args.pop
|
40
|
+
end
|
37
41
|
msg =
|
38
42
|
if args.empty? then ""
|
39
43
|
else "#{color(*args)}"
|
40
44
|
end
|
41
45
|
|
42
46
|
if !Autobuild.progress_display_enabled?
|
43
|
-
puts msg
|
47
|
+
io.puts msg
|
44
48
|
return
|
45
49
|
end
|
46
50
|
|
@@ -50,7 +54,7 @@ module Autobuild
|
|
50
54
|
end
|
51
55
|
|
52
56
|
if !silent?
|
53
|
-
puts "\r#{msg}#{" " * [size - msg.size, 0].max}"
|
57
|
+
io.puts "\r#{msg}#{" " * [size - msg.size, 0].max}"
|
54
58
|
if @last_progress_msg
|
55
59
|
print "#{@last_progress_msg}"
|
56
60
|
end
|
@@ -64,12 +68,12 @@ module Autobuild
|
|
64
68
|
|
65
69
|
# Displays an error message
|
66
70
|
def self.error(message = "")
|
67
|
-
message(" ERROR: #{message}", :red, :bold)
|
71
|
+
message(" ERROR: #{message}", :red, :bold, STDERR)
|
68
72
|
end
|
69
73
|
|
70
74
|
# Displays a warning message
|
71
75
|
def self.warn(message = "", *style)
|
72
|
-
message(" WARN: #{message}", :magenta, *style)
|
76
|
+
message(" WARN: #{message}", :magenta, *style, STDERR)
|
73
77
|
end
|
74
78
|
|
75
79
|
# @return [Boolean] true if there is some progress messages for the given
|
@@ -102,7 +106,7 @@ module Autobuild
|
|
102
106
|
progress(key, *options[:done_message])
|
103
107
|
end
|
104
108
|
progress_done(key, true)
|
105
|
-
rescue Exception
|
109
|
+
rescue Exception
|
106
110
|
progress_done(key, false)
|
107
111
|
raise
|
108
112
|
end
|
@@ -335,7 +339,7 @@ module Autobuild
|
|
335
339
|
## Display using stdout
|
336
340
|
class StdoutReporter < Reporter
|
337
341
|
def error(error)
|
338
|
-
puts "Build failed: #{error}"
|
342
|
+
STDERR.puts "Build failed: #{error}"
|
339
343
|
end
|
340
344
|
def success
|
341
345
|
puts "Build finished successfully at #{Time.now}"
|
data/lib/autobuild/subcommand.rb
CHANGED
@@ -39,11 +39,22 @@ module Autobuild
|
|
39
39
|
reset_statistics
|
40
40
|
|
41
41
|
@parallel_build_level = nil
|
42
|
+
@displayed_error_line_count = 10
|
42
43
|
class << self
|
43
44
|
# Sets the level of parallelism during the build
|
44
45
|
#
|
45
46
|
# See #parallel_build_level for detailed information
|
46
47
|
attr_writer :parallel_build_level
|
48
|
+
|
49
|
+
# set/get a value how much log lines should be displayed on errors
|
50
|
+
# this may be an integer or 'ALL' (which will be translated to -1)
|
51
|
+
# this is not using an attr_accessor to be able to validate the values
|
52
|
+
def displayed_error_line_count=(value)
|
53
|
+
@displayed_error_line_count = validate_displayed_error_line_count(value)
|
54
|
+
end
|
55
|
+
def displayed_error_line_count
|
56
|
+
@displayed_error_line_count
|
57
|
+
end
|
47
58
|
|
48
59
|
# Returns the number of processes that can run in parallel during the
|
49
60
|
# build. This is a system-wide value that can be overriden in a
|
@@ -121,31 +132,82 @@ module Autobuild
|
|
121
132
|
|
122
133
|
@processor_count
|
123
134
|
end
|
135
|
+
|
136
|
+
def self.validate_displayed_error_line_count(lines)
|
137
|
+
if lines == 'ALL'
|
138
|
+
return Float::INFINITY
|
139
|
+
elsif lines.to_i > 0
|
140
|
+
return lines.to_i
|
141
|
+
end
|
142
|
+
raise ConfigError, 'Autobuild.displayed_error_line_count can only be a positive integer or \'ALL\''
|
143
|
+
end
|
144
|
+
|
124
145
|
end
|
125
146
|
|
126
147
|
|
127
148
|
module Autobuild::Subprocess
|
128
149
|
class Failed < Exception
|
150
|
+
def retry?; @retry end
|
129
151
|
attr_reader :status
|
130
|
-
|
152
|
+
|
153
|
+
def initialize(status, do_retry)
|
131
154
|
@status = status
|
155
|
+
@retry = do_retry
|
132
156
|
end
|
133
157
|
end
|
134
158
|
|
135
159
|
CONTROL_COMMAND_NOT_FOUND = 1
|
136
160
|
CONTROL_UNEXPECTED = 2
|
137
161
|
CONTROL_INTERRUPT = 3
|
162
|
+
|
163
|
+
# Run a subcommand and return its standard output
|
164
|
+
#
|
165
|
+
# The command's standard and error outputs, as well as the full command line
|
166
|
+
# and an environment dump are saved in a log file in either the valure
|
167
|
+
# returned by target#logdir, or Autobuild.logdir if the target does not
|
168
|
+
# respond to #logdir.
|
169
|
+
#
|
170
|
+
# The subprocess priority is controlled by Autobuild.nice
|
171
|
+
#
|
172
|
+
# @param [String,(#name,#logdir,#working_directory)] target the target we
|
173
|
+
# run the subcommand for. In general, it will be a Package object (run from
|
174
|
+
# Package#run)
|
175
|
+
# @param [String] phase in which build phase this subcommand is executed
|
176
|
+
# @param [Array<String>] the command itself
|
177
|
+
# @yieldparam [String] line if a block is given, each output line from the
|
178
|
+
# command's standard output are yield to it. This is meant for progress
|
179
|
+
# display, and is disabled if Autobuild.verbose is set.
|
180
|
+
# @param [Hash] options
|
181
|
+
# @option options [String] :working_directory the directory in which the
|
182
|
+
# command should be started. If nil, runs in the current directory. The
|
183
|
+
# default is to either use the value returned by #working_directory on
|
184
|
+
# {target} if it responds to it, or nil.
|
185
|
+
# @option options [Boolean] :retry (false) controls whether a failure to
|
186
|
+
# execute this command should be retried by autobuild retry mechanisms (i.e.
|
187
|
+
# in the importers) or not. {run} will not retry the command by itself, it
|
188
|
+
# is passed as a hint for error handling clauses about whether the error
|
189
|
+
# should be retried or not
|
190
|
+
# @option options [Array<IO>] :input_streams list of input streams that
|
191
|
+
# should be fed to the command standard input. If a file needs to be given,
|
192
|
+
# the :input argument can be used as well as a shortcut
|
193
|
+
# @option options [String] :input the path to a file whose content should be
|
194
|
+
# fed to the command standard input
|
195
|
+
# @return [String] the command standard output
|
138
196
|
def self.run(target, phase, *command)
|
139
197
|
STDOUT.sync = true
|
140
198
|
|
141
199
|
input_streams = []
|
142
|
-
options = Hash
|
200
|
+
options = Hash[retry: false]
|
143
201
|
if command.last.kind_of?(Hash)
|
144
202
|
options = command.pop
|
145
203
|
options = Kernel.validate_options options,
|
146
|
-
:
|
204
|
+
input: nil, working_directory: nil, retry: false,
|
205
|
+
input_streams: []
|
147
206
|
if options[:input]
|
148
|
-
input_streams
|
207
|
+
input_streams << File.open(options[:input])
|
208
|
+
end
|
209
|
+
if options[:input_streams]
|
210
|
+
input_streams += options[:input_streams]
|
149
211
|
end
|
150
212
|
end
|
151
213
|
|
@@ -186,6 +248,7 @@ module Autobuild::Subprocess
|
|
186
248
|
end
|
187
249
|
|
188
250
|
Autobuild.register_logfile(logname)
|
251
|
+
subcommand_output = Array.new
|
189
252
|
|
190
253
|
status = File.open(logname, open_flag) do |logfile|
|
191
254
|
if Autobuild.keep_oldlogs
|
@@ -207,26 +270,20 @@ module Autobuild::Subprocess
|
|
207
270
|
if !input_streams.empty?
|
208
271
|
pread, pwrite = IO.pipe # to feed subprocess stdin
|
209
272
|
end
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
273
|
+
|
274
|
+
outread, outwrite = IO.pipe
|
275
|
+
outread.sync = true
|
276
|
+
outwrite.sync = true
|
277
|
+
|
215
278
|
cread, cwrite = IO.pipe # to control that exec goes well
|
216
279
|
|
217
280
|
if Autobuild.windows?
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
result=$?.success?
|
224
|
-
if(!result)
|
225
|
-
error = Autobuild::SubcommandFailed.new(target, command.join(" "), logname, "Systemcall")
|
226
|
-
error.phase = phase
|
227
|
-
raise error
|
281
|
+
Dir.chdir(options[:working_directory]) do
|
282
|
+
if !system(*command)
|
283
|
+
raise Failed.new($?.exitstatus, nil),
|
284
|
+
"'#{command.join(' ')}' returned status #{status.exitstatus}"
|
285
|
+
end
|
228
286
|
end
|
229
|
-
Dir.chdir(olddir)
|
230
287
|
return
|
231
288
|
end
|
232
289
|
|
@@ -278,13 +335,12 @@ module Autobuild::Subprocess
|
|
278
335
|
if !input_streams.empty?
|
279
336
|
pread.close
|
280
337
|
begin
|
281
|
-
input_streams.each do |
|
282
|
-
|
283
|
-
instream.each_line { |line| pwrite.write(line) }
|
284
|
-
end
|
338
|
+
input_streams.each do |instream|
|
339
|
+
instream.each_line { |line| pwrite.write(line) }
|
285
340
|
end
|
286
341
|
rescue Errno::ENOENT => e
|
287
|
-
raise Failed.new,
|
342
|
+
raise Failed.new(nil, false),
|
343
|
+
"cannot open input files: #{e.message}", retry: false
|
288
344
|
end
|
289
345
|
pwrite.close
|
290
346
|
end
|
@@ -296,43 +352,45 @@ module Autobuild::Subprocess
|
|
296
352
|
# An error occured
|
297
353
|
value = value.unpack('I').first
|
298
354
|
if value == CONTROL_COMMAND_NOT_FOUND
|
299
|
-
raise Failed.new,
|
355
|
+
raise Failed.new(nil, false),
|
356
|
+
"command '#{command.first}' not found"
|
300
357
|
elsif value == CONTROL_INTERRUPT
|
301
358
|
raise Interrupt, "command '#{command.first}': interrupted by user"
|
302
359
|
else
|
303
|
-
raise Failed.new,
|
360
|
+
raise Failed.new(nil, false),
|
361
|
+
"something unexpected happened"
|
304
362
|
end
|
305
363
|
end
|
306
364
|
|
307
365
|
# If the caller asked for process output, provide it to him
|
308
366
|
# line-by-line.
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
end
|
367
|
+
outwrite.close
|
368
|
+
outread.each_line do |line|
|
369
|
+
line.force_encoding('BINARY')
|
370
|
+
line = line.chomp
|
371
|
+
subcommand_output << line
|
372
|
+
|
373
|
+
if Autobuild.verbose
|
374
|
+
STDOUT.puts line
|
375
|
+
end
|
376
|
+
logfile.puts line
|
377
|
+
# Do not yield the line if Autobuild.verbose is true, as it
|
378
|
+
# would mix the progress output with the actual command
|
379
|
+
# output. Assume that if the user wants the command output,
|
380
|
+
# the autobuild progress output is unnecessary
|
381
|
+
if !Autobuild.verbose && block_given?
|
382
|
+
yield(line)
|
326
383
|
end
|
327
|
-
outread.close
|
328
384
|
end
|
385
|
+
outread.close
|
329
386
|
|
330
|
-
|
387
|
+
_, childstatus = Process.wait2(pid)
|
331
388
|
childstatus
|
332
389
|
end
|
333
390
|
|
334
391
|
if !status.exitstatus || status.exitstatus > 0
|
335
|
-
raise Failed.new(status.exitstatus
|
392
|
+
raise Failed.new(status.exitstatus, nil),
|
393
|
+
"'#{command.join(' ')}' returned status #{status.exitstatus}"
|
336
394
|
end
|
337
395
|
|
338
396
|
duration = Time.now - start_time
|
@@ -345,14 +403,16 @@ module Autobuild::Subprocess
|
|
345
403
|
if target.respond_to?(:add_stat)
|
346
404
|
target.add_stat(phase, duration)
|
347
405
|
end
|
406
|
+
subcommand_output
|
348
407
|
|
349
408
|
rescue Failed => e
|
350
|
-
error = Autobuild::SubcommandFailed.new(target, command.join(" "), logname, e.status)
|
409
|
+
error = Autobuild::SubcommandFailed.new(target, command.join(" "), logname, e.status, subcommand_output)
|
410
|
+
error.retry = if e.retry?.nil? then options[:retry]
|
411
|
+
else e.retry?
|
412
|
+
end
|
351
413
|
error.phase = phase
|
352
414
|
raise error, e.message
|
353
415
|
end
|
354
416
|
|
355
417
|
end
|
356
418
|
|
357
|
-
|
358
|
-
|