autobuild 1.24.0 → 1.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56a551f16208e61f38188d81b0b944ef6ba663fbc3155ae7e55b009f2adda2e6
4
- data.tar.gz: 60e5b9d1b8ffe8ff4e35d006960a251ef82467ee5d17adcb9d9d21e2e7f47b15
3
+ metadata.gz: e80fda7259afb401296183494e07a8a08f1ef22c2b8cab1f54577c7527aa72ed
4
+ data.tar.gz: 89a5471c0b5afb613757dd04ac92eeb2acc0fe3fdf3cb419eb729dc2c8661e98
5
5
  SHA512:
6
- metadata.gz: 30af86ba246a653daac4299675fe4b248b36b2d30750feefd567dc32c6768b9f4b60f877021253699336c5d01c54b69f1d7db6808a6d49ea12ff612f425ca01c
7
- data.tar.gz: 16e7849423378e7e5e89f0e40e7cc77173e87290954734aa86195cf15547388bce6a7b234aaf8857593e2d513b9daf4634759026706a6f2e54eb2044b7ee8b96
6
+ metadata.gz: 54d5bbccd77d298c58cc4b8e437fcb0de325252de23d83b73aafa02ad0a4c0476177913fdfc1634022dcc4b4abc90381534f081ff1d96f58a18f400c8985bc84
7
+ data.tar.gz: fa6f9ae365e2314d1844004924fbab9c6da73d5cebc7a3244bb6092462564d5538342496f85f79d2d54e2e13717dd140341571582b8867976cdfd8d86d3ddbc9
@@ -8,7 +8,9 @@ jobs:
8
8
 
9
9
  strategy:
10
10
  matrix:
11
- ruby-version: ["2.7", "2.6", "2.5"]
11
+ ruby-version:
12
+ - "3.0"
13
+ - "2.7"
12
14
 
13
15
  steps:
14
16
  - uses: actions/checkout@v2
@@ -19,7 +21,9 @@ jobs:
19
21
  uses: ruby/setup-ruby@v1
20
22
  with:
21
23
  ruby-version: ${{ matrix.ruby-version }}
24
+ - name: Remove vscode gems
25
+ run: bundle config set --local without vscode
22
26
  - name: Install dependencies
23
27
  run: bundle install
24
28
  - name: Run rubocop
25
- run: bundle exec rubocop
29
+ run: bundle exec rubocop
@@ -8,7 +8,12 @@ jobs:
8
8
 
9
9
  strategy:
10
10
  matrix:
11
- ruby-version: ["2.7", "2.6", "2.5"]
11
+ ruby-version:
12
+ - "3.2"
13
+ - "3.1"
14
+ - "3.0"
15
+ - "2.7"
16
+ - "2.5"
12
17
 
13
18
  steps:
14
19
  - uses: actions/checkout@v2
@@ -19,8 +24,14 @@ jobs:
19
24
  uses: ruby/setup-ruby@v1
20
25
  with:
21
26
  ruby-version: ${{ matrix.ruby-version }}
27
+ - name: Remove vscode gems
28
+ run: bundle config set --local without vscode
29
+ - name: Install subversion
30
+ run: sudo apt update && sudo apt install subversion
22
31
  - name: Install dependencies
23
32
  run: bundle install
33
+ - name: Enable file transport in git
34
+ run: git config --global protocol.file.allow always
24
35
  - name: Run tests
25
36
  run: bundle exec rake test
26
37
  env:
data/.gitignore CHANGED
@@ -5,4 +5,5 @@ vendor/
5
5
  .bundle
6
6
  coverage/
7
7
 
8
- .yardoc/
8
+ .yardoc/
9
+ Gemfile.lock
data/.rubocop.yml CHANGED
@@ -1,3 +1,5 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
1
3
  inherit_gem:
2
4
  rubocop-rock: defaults.yml
3
5
 
@@ -111,4 +113,4 @@ Style/GlobalStdStream:
111
113
  Enabled: false
112
114
 
113
115
  Style/OptionalBooleanParameter:
114
- Enabled: false
116
+ Enabled: false
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,14 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2024-07-10 18:16:42 UTC using RuboCop version 1.28.2.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 2
10
+ # Configuration parameters: Include.
11
+ # Include: **/*.gemspec
12
+ Gemspec/RubyVersionGlobalsUsage:
13
+ Exclude:
14
+ - 'autobuild.gemspec'
data/Gemfile CHANGED
@@ -2,12 +2,17 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
+ group :lint do
6
+ gem 'parallel', '1.24.0'
7
+ gem 'rubocop', '1.28.2'
8
+ gem 'rubocop-ast', '1.17.0'
9
+ gem 'rubocop-rock'
10
+ end
11
+
5
12
  group :vscode do
6
13
  gem 'debase', '>= 0.2.2.beta10'
7
14
  gem 'pry'
8
15
  gem 'pry-byebug'
9
- gem 'rubocop', '>= 0.6.0'
10
- gem 'rubocop-rock'
11
16
  gem 'ruby-debug-ide', '>= 0.6.0'
12
17
  gem 'solargraph'
13
18
  end
data/autobuild.gemspec CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
  .reject { |f| f.match(%r{^(test|spec|features)/}) }
25
25
 
26
26
  s.add_runtime_dependency "concurrent-ruby", "~> 1.1"
27
+ s.add_runtime_dependency "net-smtp"
27
28
  s.add_runtime_dependency "pastel", "~> 0.7.0"
28
29
  s.add_runtime_dependency "rake", "~> 13.0"
29
30
  s.add_runtime_dependency 'tty-cursor', '~> 0.7.0'
@@ -31,8 +32,9 @@ Gem::Specification.new do |s|
31
32
  s.add_runtime_dependency 'tty-screen', '~> 0.8.0'
32
33
  s.add_runtime_dependency "utilrb", "~> 3.0", ">= 3.0"
33
34
  s.add_development_dependency "fakefs"
34
- s.add_development_dependency "flexmock", '~> 2.0', ">= 2.0.0"
35
+ s.add_development_dependency "flexmock", ">= 2.4.0"
35
36
  s.add_development_dependency "minitest", "~> 5.0", ">= 5.0"
36
37
  s.add_development_dependency "simplecov"
37
38
  s.add_development_dependency "timecop"
39
+ s.add_development_dependency "webrick"
38
40
  end
@@ -1,5 +1,3 @@
1
- require 'time'
2
-
3
1
  module Autobuild
4
2
  # Parse and manipulate the information stored in a build log file (usually
5
3
  # in prefix/log/stats.log)
@@ -1,7 +1,3 @@
1
- require 'set'
2
- require 'rbconfig'
3
- require 'utilrb/hash/map_value'
4
-
5
1
  module Autobuild
6
2
  @windows = RbConfig::CONFIG["host_os"] =~ /(msdos|mswin|djgpp|mingw|[Ww]indows)/
7
3
  def self.windows?
@@ -260,6 +256,7 @@ module Autobuild
260
256
  if flag
261
257
  @inherited_variables |= names
262
258
  names.each do |env_name|
259
+ @environment[env_name] ||= []
263
260
  init_from_env(env_name)
264
261
  end
265
262
  else
@@ -1,10 +1,3 @@
1
- require 'autobuild/importer'
2
- require 'digest/sha1'
3
- require 'open-uri'
4
- require 'fileutils'
5
- require 'net/http'
6
- require 'net/https'
7
-
8
1
  module Autobuild
9
2
  class ArchiveImporter < Importer
10
3
  # rubocop:disable Naming/ConstantName
@@ -1,7 +1,3 @@
1
- require 'autobuild/config'
2
- require 'autobuild/subcommand'
3
- require 'autobuild/importer'
4
-
5
1
  module Autobuild
6
2
  class DarcsImporter < Importer
7
3
  # Creates a new importer which gets the source from the Darcs
@@ -1,10 +1,3 @@
1
- require 'fileutils'
2
- require 'autobuild/subcommand'
3
- require 'autobuild/importer'
4
- require 'utilrb/kernel/options'
5
- require 'open3'
6
- require 'English'
7
-
8
1
  module Autobuild
9
2
  class Git < Importer
10
3
  # Exception raised when a network access is needed while only_local is true
@@ -1,8 +1,3 @@
1
- require 'fileutils'
2
- require 'autobuild/subcommand'
3
- require 'autobuild/importer'
4
- require 'utilrb/kernel/options'
5
-
6
1
  module Autobuild
7
2
  class Hg < Importer
8
3
  # Creates an importer which tracks the given repository
@@ -1,7 +1,3 @@
1
- require 'autobuild/subcommand'
2
- require 'autobuild/importer'
3
- require 'rexml/document'
4
-
5
1
  module Autobuild
6
2
  class SVN < Importer
7
3
  # Creates an importer which gets the source for the Subversion URL +source+.
@@ -1,6 +1,3 @@
1
- require 'autobuild/config'
2
- require 'autobuild/exceptions'
3
-
4
1
  # This class is the base class for objects that are used to get the source from
5
2
  # various RCS into the package source directory. A list of patches to apply
6
3
  # after the import can be given in the +:patches+ option.
@@ -540,10 +537,10 @@ module Autobuild
540
537
  File.readlines(patches_file).map do |line|
541
538
  line = line.rstrip
542
539
  if line =~ /^(.*)\s+(\d+)$/
543
- path = File.expand_path($1, package.srcdir)
540
+ path = File.expand_path($1, package.importdir)
544
541
  level = Integer($2)
545
542
  else
546
- path = File.expand_path(line, package.srcdir)
543
+ path = File.expand_path(line, package.importdir)
547
544
  level = 0
548
545
  end
549
546
  [path, level, File.read(path)]
@@ -618,7 +615,7 @@ module Autobuild
618
615
  File.open(patchlist(package), 'w') do |f|
619
616
  patch_state = cur_patches.map do |path, level|
620
617
  path = Pathname.new(path).
621
- relative_path_from(Pathname.new(package.srcdir)).to_s
618
+ relative_path_from(Pathname.new(package.importdir)).to_s
622
619
  "#{path} #{level}"
623
620
  end
624
621
  f.write(patch_state.join("\n"))
@@ -1,11 +1,3 @@
1
- require 'pathname'
2
- require 'autobuild/timestamps'
3
- require 'autobuild/environment'
4
- require 'autobuild/package'
5
- require 'autobuild/subcommand'
6
- require 'shellwords'
7
- require 'fileutils'
8
-
9
1
  module Autobuild
10
2
  def self.autotools(opts, &proc)
11
3
  Autotools.new(opts, &proc)
@@ -1,6 +1,3 @@
1
- require 'autobuild/configurable'
2
- require 'autobuild/packages/gnumake'
3
-
4
1
  module Autobuild
5
2
  def self.cmake(options, &block)
6
3
  CMake.new(options, &block)
@@ -39,6 +36,11 @@ module Autobuild
39
36
 
40
37
  attr_reader :prefix_path, :module_path
41
38
 
39
+ # Arguments that will be passed to the 'make' test target
40
+ def test_args
41
+ @test_args ||= ["-V"]
42
+ end
43
+
42
44
  # Whether files that are not within CMake's install manifest but are
43
45
  # present in the prefix should be deleted. Note that the contents of
44
46
  # {#log_dir} are unaffected.
@@ -73,6 +75,9 @@ module Autobuild
73
75
  self.class.defines.merge(additional_defines).merge(defines)
74
76
  end
75
77
 
78
+ # Arguments to be passed to the 'make' test target
79
+ attr_reader :test_args
80
+
76
81
  # If true, always run cmake before make during the build
77
82
  attr_accessor :always_reconfigure
78
83
  # If true, we always remove the CMake cache before reconfiguring.
@@ -115,6 +120,7 @@ module Autobuild
115
120
  def initialize(options)
116
121
  @defines = Hash.new
117
122
  super
123
+ @test_args = self.class.test_args.dup
118
124
  @delete_obsolete_files_in_prefix = self.class.
119
125
  delete_obsolete_files_in_prefix?
120
126
  end
@@ -272,10 +278,10 @@ module Autobuild
272
278
  def common_utility_handling( # rubocop:disable Metrics/ParameterLists
273
279
  utility,
274
280
  target,
275
- *args,
276
281
  start_msg,
277
282
  done_msg,
278
- post_process: nil
283
+ post_process: nil,
284
+ args: []
279
285
  )
280
286
  utility.source_ref_dir = builddir
281
287
  utility.task do
@@ -283,6 +289,9 @@ module Autobuild
283
289
  if internal_doxygen_mode?
284
290
  run_doxygen
285
291
  else
292
+ unless args.empty?
293
+ args = ["ARGS=#{args.map { |a| %("#{a}") }.join(' ')}"]
294
+ end
286
295
  run(utility.name,
287
296
  Autobuild.tool(:make),
288
297
  "-j#{parallel_build_level}",
@@ -322,9 +331,10 @@ module Autobuild
322
331
 
323
332
  def with_tests(target = 'test', &block)
324
333
  common_utility_handling(
325
- test_utility, target, "ARGS=-V",
334
+ test_utility, target,
326
335
  "running tests for %s",
327
336
  "successfully ran tests for %s",
337
+ args: test_args,
328
338
  post_process: coverage_block, &block)
329
339
  end
330
340
 
@@ -1,7 +1,3 @@
1
- require 'autobuild/packages/autotools'
2
- require 'open3'
3
- require 'autobuild/pkgconfig'
4
-
5
1
  module Autobuild
6
2
  def self.genom(opts, &proc)
7
3
  GenomModule.new(opts, &proc)
@@ -1,5 +1,3 @@
1
- require 'rubygems/version'
2
-
3
1
  module Autobuild
4
2
  def self.reset_gnumake_detection
5
3
  @make_is_gnumake = Hash.new
@@ -1,6 +1,3 @@
1
- require 'autobuild/timestamps'
2
- require 'autobuild/package'
3
-
4
1
  module Autobuild
5
2
  def self.import(spec, &proc)
6
3
  ImporterPackage.new(spec, &proc)
@@ -1,5 +1,3 @@
1
- require 'autobuild/pkgconfig'
2
-
3
1
  module Autobuild
4
2
  class InstalledPkgConfig < Package
5
3
  attr_reader :pkgconfig, :prefix
@@ -1,6 +1,3 @@
1
- require 'autobuild/configurable'
2
- require 'open3'
3
-
4
1
  # Main Autobuild module
5
2
  module Autobuild
6
3
  def self.python(opts, &proc)
@@ -88,7 +85,7 @@ module Autobuild
88
85
 
89
86
  # Install the result in prefix
90
87
  def install
91
- return unless install_mode?
88
+ return super unless install_mode?
92
89
 
93
90
  command = generate_install_command
94
91
  command << '--force' if @forced
@@ -1,6 +1,3 @@
1
- require "concurrent/atomic/atomic_boolean"
2
- require "concurrent/array"
3
-
4
1
  module Autobuild
5
2
  # Management of the progress display
6
3
  class ProgressDisplay
@@ -277,7 +274,7 @@ module Autobuild
277
274
  until messages.empty?
278
275
  msg = messages.shift.strip
279
276
  margin = messages.empty? ? 1 : 2
280
- if lines.last.size + margin + msg.size > width
277
+ if lines.last.size + margin + msg.size + 1 > width
281
278
  lines.last << ","
282
279
  lines << +""
283
280
  lines.last << indent << indent << msg
@@ -1,5 +1,6 @@
1
- require 'autobuild/exceptions'
2
- require 'pastel'
1
+ require "pastel"
2
+ require "concurrent/atomic/atomic_boolean"
3
+ require "concurrent/array"
3
4
 
4
5
  module Autobuild
5
6
  @colorizer = Pastel.new
@@ -1,9 +1,3 @@
1
- require 'set'
2
- require 'autobuild/exceptions'
3
- require 'autobuild/reporting'
4
- require 'fcntl'
5
- require 'English'
6
-
7
1
  module Autobuild
8
2
  @logfiles = Set.new
9
3
  def self.clear_logfiles
@@ -165,10 +159,6 @@ module Autobuild::Subprocess # rubocop:disable Style/ClassAndModuleChildren
165
159
  end
166
160
  end
167
161
 
168
- CONTROL_COMMAND_NOT_FOUND = 1
169
- CONTROL_UNEXPECTED = 2
170
- CONTROL_INTERRUPT = 3
171
-
172
162
  @transparent_mode = false
173
163
 
174
164
  def self.transparent_mode?
@@ -212,7 +202,7 @@ module Autobuild::Subprocess # rubocop:disable Style/ClassAndModuleChildren
212
202
  # @option options [String] :input the path to a file whose content should be
213
203
  # fed to the command standard input
214
204
  # @return [String] the command standard output
215
- def self.run(target, phase, *command)
205
+ def self.run(target, phase, *command, &output_filter)
216
206
  STDOUT.sync = true
217
207
 
218
208
  input_streams = []
@@ -242,13 +232,8 @@ module Autobuild::Subprocess # rubocop:disable Style/ClassAndModuleChildren
242
232
  command.reject! { |o| o.nil? || (o.respond_to?(:empty?) && o.empty?) }
243
233
  command.collect!(&:to_s)
244
234
 
245
- if target.respond_to?(:name)
246
- target_name = target.name
247
- target_type = target.class
248
- else
249
- target_name = target.to_str
250
- target_type = nil
251
- end
235
+ target_name, target_type = target_argument_to_name_and_type(target)
236
+
252
237
  logdir = if target.respond_to?(:logdir)
253
238
  target.logdir
254
239
  else
@@ -259,27 +244,6 @@ module Autobuild::Subprocess # rubocop:disable Style/ClassAndModuleChildren
259
244
  options[:working_directory] ||= target.working_directory
260
245
  end
261
246
 
262
- logname = File.join(logdir, "#{target_name.gsub(/:/, '_')}-"\
263
- "#{phase.to_s.gsub(/:/, '_')}.log")
264
- unless File.directory?(File.dirname(logname))
265
- FileUtils.mkdir_p File.dirname(logname)
266
- end
267
-
268
- if Autobuild.verbose
269
- Autobuild.message "#{target_name}: running #{command.join(' ')}\n"\
270
- " (output goes to #{logname})"
271
- end
272
-
273
- open_flag = if Autobuild.keep_oldlogs then 'a'
274
- elsif Autobuild.registered_logfile?(logname) then 'a'
275
- else
276
- 'w'
277
- end
278
- open_flag << ":BINARY"
279
-
280
- Autobuild.register_logfile(logname)
281
- subcommand_output = Array.new
282
-
283
247
  env = options[:env].dup
284
248
  if options[:env_inherit]
285
249
  ENV.each do |k, v|
@@ -287,169 +251,101 @@ module Autobuild::Subprocess # rubocop:disable Style/ClassAndModuleChildren
287
251
  end
288
252
  end
289
253
 
290
- status = File.open(logname, open_flag) do |logfile|
291
- logfile.puts if Autobuild.keep_oldlogs
292
- logfile.puts
293
- logfile.puts "#{Time.now}: running"
294
- logfile.puts " #{command.join(' ')}"
295
- logfile.puts "with environment:"
296
- env.keys.sort.each do |key|
297
- if (value = env[key])
298
- logfile.puts " '#{key}'='#{value}'"
299
- end
300
- end
301
- logfile.puts
302
- logfile.puts "#{Time.now}: running"
303
- logfile.puts " #{command.join(' ')}"
304
- logfile.flush
305
- logfile.sync = true
306
-
307
- unless input_streams.empty?
308
- pread, pwrite = IO.pipe # to feed subprocess stdin
309
- end
254
+ if Autobuild.windows?
255
+ windows_support(options, command)
256
+ return
257
+ end
310
258
 
311
- outread, outwrite = IO.pipe
312
- outread.sync = true
313
- outwrite.sync = true
259
+ logname = compute_log_path(target_name, phase, logdir)
314
260
 
315
- cread, cwrite = IO.pipe # to control that exec goes well
261
+ status, subcommand_output = open_logfile(logname) do |logfile|
262
+ logfile_header(logfile, command, env)
316
263
 
317
- if Autobuild.windows?
318
- Dir.chdir(options[:working_directory]) do
319
- unless system(*command)
320
- exit_code = $CHILD_STATUS.exitstatus
321
- raise Failed.new(exit_code, nil),
322
- "'#{command.join(' ')}' returned status #{exit_code}"
323
- end
324
- end
325
- return # rubocop:disable Lint/NonLocalExitFromIterator
264
+ if Autobuild.verbose
265
+ Autobuild.message "#{target_name}: running #{command.join(' ')}\n"\
266
+ " (output goes to #{logname})"
326
267
  end
327
268
 
328
- cwrite.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
329
-
330
- pid = fork do
331
- logfile.puts "in directory #{options[:working_directory] || Dir.pwd}"
332
-
333
- cwrite.sync = true
334
- if Autobuild.nice
335
- Process.setpriority(Process::PRIO_PROCESS, 0, Autobuild.nice)
336
- end
337
-
338
- outread.close
339
- $stderr.reopen(outwrite.dup)
340
- $stdout.reopen(outwrite.dup)
341
-
342
- unless input_streams.empty?
343
- pwrite.close
344
- $stdin.reopen(pread)
345
- end
269
+ unless input_streams.empty?
270
+ stdin_r, stdin_w = IO.pipe # to feed subprocess stdin
271
+ end
346
272
 
347
- exec(env, *command,
348
- chdir: options[:working_directory] || Dir.pwd,
349
- close_others: false)
273
+ out_r, out_w = IO.pipe
274
+ out_r.sync = true
275
+ out_w.sync = true
276
+
277
+ logfile.puts "Spawning"
278
+ stdin_redir = { :in => stdin_r } if stdin_r
279
+ begin
280
+ pid = spawn(
281
+ env, *command,
282
+ {
283
+ :chdir => options[:working_directory] || Dir.pwd,
284
+ :close_others => false,
285
+ %I[err out] => out_w
286
+ }.merge(stdin_redir || {})
287
+ )
288
+ logfile.puts "Spawned, PID=#{pid}"
350
289
  rescue Errno::ENOENT
351
- cwrite.write([CONTROL_COMMAND_NOT_FOUND].pack('I'))
352
- exit(100)
353
- rescue Interrupt
354
- cwrite.write([CONTROL_INTERRUPT].pack('I'))
355
- exit(100)
356
- rescue ::Exception => e
357
- STDERR.puts e
358
- STDERR.puts e.backtrace.join("\n ")
359
- cwrite.write([CONTROL_UNEXPECTED].pack('I'))
360
- exit(100)
290
+ raise Failed.new(nil, false), "command '#{command.first}' not found"
361
291
  end
362
292
 
363
- readbuffer = StringIO.new
293
+ if Autobuild.nice
294
+ Process.setpriority(Process::PRIO_PROCESS, pid, Autobuild.nice)
295
+ end
364
296
 
365
297
  # Feed the input
366
298
  unless input_streams.empty?
367
- pread.close
368
- begin
369
- input_streams.each do |instream|
370
- instream.each_line do |line|
371
- while IO.select([outread], nil, nil, 0)
372
- readbuffer.write(outread.readpartial(128))
373
- end
374
- pwrite.write(line)
375
- end
376
- end
377
- rescue Errno::ENOENT => e
378
- raise Failed.new(nil, false),
379
- "cannot open input files: #{e.message}", retry: false
380
- end
381
- pwrite.close
299
+ logfile.puts "Feeding STDIN"
300
+ stdin_r.close
301
+ readbuffer = feed_input(input_streams, out_r, stdin_w)
302
+ stdin_w.close
382
303
  end
383
304
 
384
- # Get control status
385
- cwrite.close
386
- value = cread.read(4)
387
- if value
388
- # An error occured
389
- value = value.unpack1('I')
390
- case value
391
- when CONTROL_COMMAND_NOT_FOUND
392
- raise Failed.new(nil, false), "command '#{command.first}' not found"
393
- when CONTROL_INTERRUPT
394
- raise Interrupt, "command '#{command.first}': interrupted by user"
395
- else
396
- raise Failed.new(nil, false), "something unexpected happened"
397
- end
398
- end
399
-
400
- transparent_prefix = "#{target_name}:#{phase}: "
401
- transparent_prefix = "#{target_type}:#{transparent_prefix}" if target_type
402
-
403
305
  # If the caller asked for process output, provide it to him
404
306
  # line-by-line.
405
- outwrite.close
307
+ out_w.close
406
308
 
407
309
  unless input_streams.empty?
408
- readbuffer.write(outread.read)
310
+ readbuffer.write(out_r.read)
409
311
  readbuffer.seek(0)
410
- outread.close
411
- outread = readbuffer
312
+ out_r.close
313
+ out_r = readbuffer
412
314
  end
413
315
 
414
- outread.each_line do |line|
415
- line.force_encoding(options[:encoding])
416
- line = line.chomp
417
- subcommand_output << line
418
-
419
- logfile.puts line
420
-
421
- if Autobuild.verbose || transparent_mode?
422
- STDOUT.puts "#{transparent_prefix}#{line}"
423
- elsif block_given?
424
- # Do not yield
425
- # would mix the progress output with the actual command
426
- # output. Assume that if the user wants the command output,
427
- # the autobuild progress output is unnecessary
428
- yield(line)
429
- end
430
- end
431
- outread.close
316
+ transparent_prefix =
317
+ transparent_output_prefix(target_name, phase, target_type)
318
+ logfile.puts "Processing command output"
319
+ subcommand_output = process_output(
320
+ out_r, logfile, transparent_prefix, options[:encoding], &output_filter
321
+ )
322
+ out_r.close
432
323
 
324
+ logfile.puts "Waiting for #{pid} to finish"
433
325
  _, childstatus = Process.wait2(pid)
434
326
  logfile.puts "Exit: #{childstatus}"
435
- childstatus
327
+ [childstatus, subcommand_output]
436
328
  end
437
329
 
438
- if !status.exitstatus || status.exitstatus > 0
439
- if status.termsig == 2 # SIGINT == 2
440
- raise Interrupt, "subcommand #{command.join(' ')} interrupted"
441
- end
330
+ handle_exit_status(status, command)
331
+ update_stats(target, phase, start_time)
442
332
 
443
- if status.termsig
444
- raise Failed.new(status.exitstatus, nil),
445
- "'#{command.join(' ')}' terminated by signal #{status.termsig}"
446
- else
447
- raise Failed.new(status.exitstatus, nil),
448
- "'#{command.join(' ')}' returned status #{status.exitstatus}"
449
- end
450
- end
333
+ subcommand_output
334
+ rescue Failed => e
335
+ error = Autobuild::SubcommandFailed.new(
336
+ target, command.join(" "), logname, e.status, subcommand_output || []
337
+ )
338
+ error.retry = if e.retry?.nil? then options[:retry]
339
+ else
340
+ e.retry?
341
+ end
342
+ error.phase = phase
343
+ raise error, e.message
344
+ end
451
345
 
346
+ def self.update_stats(target, phase, start_time)
452
347
  duration = Time.now - start_time
348
+ target_name, = target_argument_to_name_and_type(target)
453
349
  Autobuild.add_stat(target, phase, duration)
454
350
  FileUtils.mkdir_p(Autobuild.logdir)
455
351
  File.open(File.join(Autobuild.logdir, "stats.log"), 'a') do |io|
@@ -458,15 +354,162 @@ module Autobuild::Subprocess # rubocop:disable Style/ClassAndModuleChildren
458
354
  io.puts "#{formatted_time} #{target_name} #{phase} #{duration}"
459
355
  end
460
356
  target.add_stat(phase, duration) if target.respond_to?(:add_stat)
357
+ end
358
+
359
+ def self.target_argument_to_name_and_type(target)
360
+ if target.respond_to?(:name)
361
+ [target.name, target.class]
362
+ else
363
+ [target.to_str, nil]
364
+ end
365
+ end
366
+
367
+ def self.target_argument_to_name(target)
368
+ if target.respond_to?(:name)
369
+ target.name
370
+ else
371
+ target.to_str
372
+ end
373
+ end
374
+
375
+ def self.target_argument_to_type(target, type)
376
+ return type if type
377
+
378
+ target.class if target.respond_to?(:name)
379
+ end
380
+
381
+ def self.handle_exit_status(status, command)
382
+ return if status.exitstatus == 0
383
+
384
+ if status.termsig == 2 # SIGINT == 2
385
+ raise Interrupt, "subcommand #{command.join(' ')} interrupted"
386
+ end
387
+
388
+ if status.termsig
389
+ raise Failed.new(status.exitstatus, nil),
390
+ "'#{command.join(' ')}' terminated by signal #{status.termsig}"
391
+ else
392
+ raise Failed.new(status.exitstatus, nil),
393
+ "'#{command.join(' ')}' returned status #{status.exitstatus}"
394
+ end
395
+ end
396
+
397
+ def self.windows_support(options, command)
398
+ Dir.chdir(options[:working_directory]) do
399
+ unless system(*command)
400
+ exit_code = $CHILD_STATUS.exitstatus
401
+ raise Failed.new(exit_code, nil),
402
+ "'#{command.join(' ')}' returned status #{exit_code}"
403
+ end
404
+ end
405
+ end
406
+
407
+ def self.compute_log_path(target_name, phase, logdir)
408
+ File.join(logdir, "#{target_name.gsub(/:/, '_')}-"\
409
+ "#{phase.to_s.gsub(/:/, '_')}.log")
410
+ end
411
+
412
+ def self.open_logfile(logname, &block)
413
+ open_flag = if Autobuild.keep_oldlogs then 'a'
414
+ elsif Autobuild.registered_logfile?(logname) then 'a'
415
+ else
416
+ 'w'
417
+ end
418
+ open_flag << ":BINARY"
419
+
420
+ unless File.directory?(File.dirname(logname))
421
+ FileUtils.mkdir_p File.dirname(logname)
422
+ end
423
+
424
+ Autobuild.register_logfile(logname)
425
+ File.open(logname, open_flag, &block)
426
+ end
427
+
428
+ def self.logfile_header(logfile, command, env)
429
+ logfile.puts if Autobuild.keep_oldlogs
430
+ logfile.puts
431
+ logfile.puts "#{Time.now}: running"
432
+ logfile.puts " #{command.join(' ')}"
433
+ logfile.puts "with environment:"
434
+ env.keys.sort.each do |key|
435
+ if (value = env[key])
436
+ logfile.puts " '#{key}'='#{value}'"
437
+ end
438
+ end
439
+ logfile.puts
440
+ logfile.puts "#{Time.now}: running"
441
+ logfile.puts " #{command.join(' ')}"
442
+ logfile.flush
443
+ logfile.sync = true
444
+ end
445
+
446
+ def self.outpipe_each_line(out_r)
447
+ buffer = +""
448
+ while (data = out_r.readpartial(1024))
449
+ buffer << data
450
+ scanner = StringScanner.new(buffer)
451
+ while (line = scanner.scan_until(/\n/))
452
+ yield line
453
+ end
454
+ buffer = scanner.rest.dup
455
+ end
456
+ rescue EOFError
457
+ scanner = StringScanner.new(buffer)
458
+ while (line = scanner.scan_until(/\n/))
459
+ yield line
460
+ end
461
+ yield scanner.rest unless scanner.rest.empty?
462
+ end
463
+
464
+ def self.process_output(
465
+ out_r, logfile, transparent_prefix, encoding, &filter
466
+ )
467
+ subcommand_output = []
468
+ outpipe_each_line(out_r) do |line|
469
+ line.force_encoding(encoding)
470
+ line = line.chomp
471
+ subcommand_output << line
472
+
473
+ logfile.puts line
474
+
475
+ if Autobuild.verbose || transparent_mode?
476
+ STDOUT.puts "#{transparent_prefix}#{line}"
477
+ elsif filter
478
+ # Do not yield
479
+ # would mix the progress output with the actual command
480
+ # output. Assume that if the user wants the command output,
481
+ # the autobuild progress output is unnecessary
482
+ filter.call(line)
483
+ end
484
+ end
461
485
  subcommand_output
462
- rescue Failed => e
463
- error = Autobuild::SubcommandFailed.new(target, command.join(" "),
464
- logname, e.status, subcommand_output)
465
- error.retry = if e.retry?.nil? then options[:retry]
466
- else
467
- e.retry?
468
- end
469
- error.phase = phase
470
- raise error, e.message
486
+ end
487
+
488
+ def self.transparent_output_prefix(target_name, phase, target_type)
489
+ prefix = "#{target_name}:#{phase}: "
490
+ return prefix unless target_type
491
+
492
+ "#{target_type}:#{prefix}"
493
+ end
494
+
495
+ def self.feed_input(input_streams, out_r, stdin_w)
496
+ readbuffer = StringIO.new
497
+ input_streams.each do |instream|
498
+ instream.each_line do |line|
499
+ # Read the process output to avoid having it block on a full pipe
500
+ begin
501
+ loop do
502
+ readbuffer.write(out_r.read_nonblock(1024))
503
+ end
504
+ rescue IO::WaitReadable # rubocop:disable Lint/SuppressedException
505
+ end
506
+
507
+ stdin_w.write(line)
508
+ end
509
+ end
510
+ readbuffer
511
+ rescue Errno::ENOENT => e
512
+ raise Failed.new(nil, false),
513
+ "cannot open input files: #{e.message}", retry: false
471
514
  end
472
515
  end
@@ -1,3 +1,3 @@
1
1
  module Autobuild
2
- VERSION = "1.24.0".freeze unless defined? Autobuild::VERSION
2
+ VERSION = "1.25.1".freeze unless defined? Autobuild::VERSION
3
3
  end
data/lib/autobuild.rb CHANGED
@@ -11,7 +11,6 @@ module Autobuild
11
11
  extend Logger::Root('Autobuild', Logger::INFO)
12
12
  end
13
13
 
14
- require 'net/smtp'
15
14
  require 'socket'
16
15
  require 'etc'
17
16
  require 'find'
@@ -21,8 +20,27 @@ require 'rake/tasklib'
21
20
  require 'fileutils'
22
21
  require 'optparse'
23
22
  require 'singleton'
23
+ require 'open3'
24
+ require 'English'
24
25
  require 'pastel'
26
+ require 'fcntl'
27
+ require 'rexml'
25
28
  require 'tty-prompt'
29
+ require 'time'
30
+ require 'set'
31
+ require 'rbconfig'
32
+ require 'digest/sha1'
33
+ require 'open-uri'
34
+ require 'net/http'
35
+ require 'net/https'
36
+ require 'net/smtp'
37
+ require 'rubygems/version'
38
+
39
+ require "concurrent/atomic/atomic_boolean"
40
+ require "concurrent/array"
41
+
42
+ require 'utilrb/hash/map_value'
43
+ require 'utilrb/kernel/options'
26
44
  require 'autobuild/tools'
27
45
 
28
46
  require 'autobuild/version'
@@ -31,7 +49,7 @@ require 'autobuild/exceptions'
31
49
  require 'autobuild/pkgconfig'
32
50
  require 'autobuild/reporting'
33
51
  require 'autobuild/mail_reporter'
34
- require 'autobuild/subcommand'
52
+ require 'autobuild/subprocess'
35
53
  require 'autobuild/timestamps'
36
54
  require 'autobuild/parallel'
37
55
  require 'autobuild/utility'
@@ -50,6 +68,7 @@ require 'autobuild/import/tar'
50
68
  require 'autobuild/package'
51
69
  require 'autobuild/configurable'
52
70
  require 'autobuild/packages/autotools'
71
+ require 'autobuild/packages/gnumake'
53
72
  require 'autobuild/packages/cmake'
54
73
  require 'autobuild/packages/genom'
55
74
  require 'autobuild/packages/import'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: autobuild
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.24.0
4
+ version: 1.25.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Joyeux
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-11 00:00:00.000000000 Z
11
+ date: 2025-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: net-smtp
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: pastel
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -132,22 +146,16 @@ dependencies:
132
146
  name: flexmock
133
147
  requirement: !ruby/object:Gem::Requirement
134
148
  requirements:
135
- - - "~>"
136
- - !ruby/object:Gem::Version
137
- version: '2.0'
138
149
  - - ">="
139
150
  - !ruby/object:Gem::Version
140
- version: 2.0.0
151
+ version: 2.4.0
141
152
  type: :development
142
153
  prerelease: false
143
154
  version_requirements: !ruby/object:Gem::Requirement
144
155
  requirements:
145
- - - "~>"
146
- - !ruby/object:Gem::Version
147
- version: '2.0'
148
156
  - - ">="
149
157
  - !ruby/object:Gem::Version
150
- version: 2.0.0
158
+ version: 2.4.0
151
159
  - !ruby/object:Gem::Dependency
152
160
  name: minitest
153
161
  requirement: !ruby/object:Gem::Requirement
@@ -196,6 +204,20 @@ dependencies:
196
204
  - - ">="
197
205
  - !ruby/object:Gem::Version
198
206
  version: '0'
207
+ - !ruby/object:Gem::Dependency
208
+ name: webrick
209
+ requirement: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - ">="
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :development
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ requirements:
218
+ - - ">="
219
+ - !ruby/object:Gem::Version
220
+ version: '0'
199
221
  description: Collection of classes to handle build systems (CMake, autotools, ...)
200
222
  and import mechanisms (tarballs, CVS, SVN, git, ...). It also offers a Rake integration
201
223
  to import and build such software packages. It is the backbone of the autoproj (http://rock-robotics.org/autoproj)
@@ -210,6 +232,7 @@ files:
210
232
  - ".github/workflows/test.yml"
211
233
  - ".gitignore"
212
234
  - ".rubocop.yml"
235
+ - ".rubocop_todo.yml"
213
236
  - Changes.txt
214
237
  - Gemfile
215
238
  - Manifest.txt
@@ -249,7 +272,7 @@ files:
249
272
  - lib/autobuild/progress_display.rb
250
273
  - lib/autobuild/rake_task_extension.rb
251
274
  - lib/autobuild/reporting.rb
252
- - lib/autobuild/subcommand.rb
275
+ - lib/autobuild/subprocess.rb
253
276
  - lib/autobuild/test.rb
254
277
  - lib/autobuild/test_utility.rb
255
278
  - lib/autobuild/timestamps.rb