autobuild 1.19.0 → 1.22.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/lint.yml +25 -0
  3. data/.github/workflows/test.yml +30 -0
  4. data/.rubocop.yml +14 -7
  5. data/autobuild.gemspec +8 -6
  6. data/bin/autobuild +1 -1
  7. data/lib/autobuild/build_logfile.rb +1 -2
  8. data/lib/autobuild/config.rb +18 -5
  9. data/lib/autobuild/configurable.rb +3 -1
  10. data/lib/autobuild/environment.rb +28 -45
  11. data/lib/autobuild/exceptions.rb +11 -5
  12. data/lib/autobuild/import/archive.rb +31 -22
  13. data/lib/autobuild/import/cvs.rb +6 -6
  14. data/lib/autobuild/import/darcs.rb +4 -4
  15. data/lib/autobuild/import/git-lfs.rb +4 -4
  16. data/lib/autobuild/import/git.rb +149 -70
  17. data/lib/autobuild/import/hg.rb +7 -7
  18. data/lib/autobuild/import/svn.rb +15 -9
  19. data/lib/autobuild/importer.rb +38 -38
  20. data/lib/autobuild/mail_reporter.rb +5 -2
  21. data/lib/autobuild/package.rb +24 -14
  22. data/lib/autobuild/packages/autotools.rb +4 -9
  23. data/lib/autobuild/packages/cmake.rb +16 -7
  24. data/lib/autobuild/packages/dummy.rb +0 -4
  25. data/lib/autobuild/packages/gnumake.rb +1 -1
  26. data/lib/autobuild/packages/orogen.rb +11 -4
  27. data/lib/autobuild/packages/pkgconfig.rb +2 -2
  28. data/lib/autobuild/packages/python.rb +1 -2
  29. data/lib/autobuild/packages/ruby.rb +5 -5
  30. data/lib/autobuild/parallel.rb +12 -17
  31. data/lib/autobuild/pkgconfig.rb +1 -0
  32. data/lib/autobuild/progress_display.rb +130 -49
  33. data/lib/autobuild/rake_task_extension.rb +6 -0
  34. data/lib/autobuild/reporting.rb +20 -7
  35. data/lib/autobuild/subcommand.rb +24 -23
  36. data/lib/autobuild/test_utility.rb +2 -1
  37. data/lib/autobuild/timestamps.rb +3 -3
  38. data/lib/autobuild/utility.rb +29 -9
  39. data/lib/autobuild/version.rb +1 -1
  40. data/lib/autobuild.rb +0 -3
  41. metadata +42 -26
  42. data/.travis.yml +0 -19
@@ -17,9 +17,9 @@ module Autobuild
17
17
  # @option options [String] :branch (default) the branch to track
18
18
  def initialize(repository, options = {})
19
19
  hgopts, _common = Kernel.filter_options options,
20
- branch: 'default'
20
+ branch: 'default'
21
21
  sourceopts, common = Kernel.filter_options options,
22
- :repository_id, :source_id
22
+ :repository_id, :source_id
23
23
 
24
24
  super(common)
25
25
  @branch = hgopts[:branch]
@@ -48,8 +48,8 @@ module Autobuild
48
48
  def validate_importdir(package)
49
49
  unless File.directory?(File.join(package.importdir, '.hg'))
50
50
  raise ConfigException.new(package, 'import'),
51
- "while importing #{package.name}, "\
52
- "#{package.importdir} is not a hg repository"
51
+ "while importing #{package.name}, "\
52
+ "#{package.importdir} is not a hg repository"
53
53
  end
54
54
  end
55
55
 
@@ -61,9 +61,9 @@ module Autobuild
61
61
  end
62
62
  validate_importdir(package)
63
63
  package.run(:import, Autobuild.tool('hg'), 'pull',
64
- repository, retry: true, working_directory: package.importdir)
64
+ repository, retry: true, working_directory: package.importdir)
65
65
  package.run(:import, Autobuild.tool('hg'), 'update',
66
- branch, working_directory: package.importdir)
66
+ branch, working_directory: package.importdir)
67
67
  true # no easy to know if package was updated, keep previous behavior
68
68
  end
69
69
 
@@ -72,7 +72,7 @@ module Autobuild
72
72
  FileUtils.mkdir_p(base_dir) unless File.directory?(base_dir)
73
73
 
74
74
  package.run(:import, Autobuild.tool('hg'), 'clone',
75
- '-u', branch, repository, package.importdir, retry: true)
75
+ '-u', branch, repository, package.importdir, retry: true)
76
76
  end
77
77
  end
78
78
 
@@ -14,9 +14,11 @@ module Autobuild
14
14
  # Autobuild.programs['svn'] = 'my_svn_tool'
15
15
  def initialize(svnroot, options = {})
16
16
  svnroot = [*svnroot].join("/")
17
- svnopts, common = Kernel.filter_options options,
17
+ svnopts, common = Kernel.filter_options(
18
+ options,
18
19
  :svnup => [], :svnco => [], :revision => nil,
19
20
  :repository_id => "svn:#{svnroot}"
21
+ )
20
22
  common[:repository_id] = svnopts.delete(:repository_id)
21
23
  relocate(svnroot, svnopts)
22
24
  super(common.merge(repository_id: svnopts[:repository_id]))
@@ -67,7 +69,7 @@ module Autobuild
67
69
  revision = svninfo.grep(/^Revision: /).first
68
70
  unless revision
69
71
  raise ConfigException.new(package, 'import'),
70
- "cannot get SVN information for #{package.importdir}"
72
+ "cannot get SVN information for #{package.importdir}"
71
73
  end
72
74
  revision =~ /Revision: (\d+)/
73
75
  Integer($1)
@@ -79,7 +81,9 @@ module Autobuild
79
81
  # @return [String]
80
82
  # @raises (see svn_info)
81
83
  def vcs_fingerprint(package)
82
- Digest::SHA1.hexdigest(svn_info(package).grep(/^(URL|Revision):/).sort.join("\n"))
84
+ Digest::SHA1.hexdigest(
85
+ svn_info(package).grep(/^(URL|Revision):/).sort.join("\n")
86
+ )
83
87
  end
84
88
 
85
89
  # Returns the URL of the remote SVN repository
@@ -93,7 +97,7 @@ module Autobuild
93
97
  url = svninfo.grep(/^URL: /).first
94
98
  unless url
95
99
  raise ConfigException.new(package, 'import'),
96
- "cannot get SVN information for #{package.importdir}"
100
+ "cannot get SVN information for #{package.importdir}"
97
101
  end
98
102
  url.chomp =~ /URL: (.+)/
99
103
  $1
@@ -165,8 +169,9 @@ module Autobuild
165
169
  Hash.new
166
170
  end
167
171
 
168
- options, other_options = Kernel.filter_options options,
169
- working_directory: package.importdir, retry: true
172
+ options, other_options = Kernel.filter_options(
173
+ options, working_directory: package.importdir, retry: true
174
+ )
170
175
  options = options.merge(other_options)
171
176
  package.run(:import, Autobuild.tool(:svn), *args, options, &block)
172
177
  end
@@ -203,7 +208,8 @@ module Autobuild
203
208
 
204
209
  unless svninfo.grep(/is not a working copy/).empty?
205
210
  raise ConfigException.new(package, 'import'),
206
- "#{package.importdir} does not appear to be a Subversion working copy"
211
+ "#{package.importdir} does not appear to be a "\
212
+ "Subversion working copy"
207
213
  end
208
214
  svninfo
209
215
  ensure
@@ -241,8 +247,8 @@ module Autobuild
241
247
 
242
248
  def checkout(package, _options = Hash.new) # :nodoc:
243
249
  run_svn(package, 'co', "--non-interactive", *@options_co,
244
- svnroot, package.importdir,
245
- working_directory: nil)
250
+ svnroot, package.importdir,
251
+ working_directory: nil)
246
252
  end
247
253
  end
248
254
 
@@ -107,7 +107,11 @@ module Autobuild
107
107
  # @return [Array<String>,nil]
108
108
  # @see .cache_dirs
109
109
  def self.default_cache_dirs
110
- [@default_cache_dirs] if @default_cache_dirs ||= ENV['AUTOBUILD_CACHE_DIR']
110
+ if @default_cache_dirs
111
+ @default_cache_dirs
112
+ elsif (from_env = ENV['AUTOBUILD_CACHE_DIR'])
113
+ @default_cache_dirs = [from_env]
114
+ end
111
115
  end
112
116
 
113
117
  # Sets the cache directory for a given importer type
@@ -199,7 +203,8 @@ module Autobuild
199
203
 
200
204
  patches_fingerprint_string = patches_fingerprint(package)
201
205
  if patches_fingerprint_string
202
- Digest::SHA1.hexdigest(vcs_fingerprint_string + patches_fingerprint_string)
206
+ Digest::SHA1.hexdigest(vcs_fingerprint_string +
207
+ patches_fingerprint_string)
203
208
  elsif patches.empty?
204
209
  vcs_fingerprint_string
205
210
  end
@@ -207,16 +212,19 @@ module Autobuild
207
212
 
208
213
  # basic fingerprint of the package and its dependencies
209
214
  def vcs_fingerprint(package)
210
- #each importer type should implement its own
211
- Autoproj.warn "Fingerprint in #{package.name} has not been implemented for this type of packages, results should be discarded"
212
- return nil
215
+ # each importer type should implement its own
216
+ Autoproj.warn "Fingerprint in #{package.name} has not been implemented "\
217
+ "for this type of packages, results should be discarded"
218
+ nil
213
219
  end
214
220
 
215
221
  # fingerprint for patches associated to this package
216
222
  def patches_fingerprint(package)
217
223
  cur_patches = currently_applied_patches(package)
218
- cur_patches.map(&:shift) #leave only level and source information
219
- Digest::SHA1.hexdigest(cur_patches.sort.flatten.join("")) if !patches.empty? && cur_patches
224
+ cur_patches.map(&:shift) # leave only level and source information
225
+ if !patches.empty? && cur_patches
226
+ Digest::SHA1.hexdigest(cur_patches.sort.flatten.join(""))
227
+ end
220
228
  end
221
229
 
222
230
  # Sets the number of times update / checkout should be retried before giving
@@ -310,12 +318,10 @@ module Autobuild
310
318
  end
311
319
 
312
320
  # Enumerate the post-import hooks for this importer
313
- def each_post_hook(error: false)
321
+ def each_post_hook(error: false, &block)
314
322
  return enum_for(__method__, error: false) unless block_given?
315
323
 
316
- self.class.each_post_hook(error: error) do |callback|
317
- yield(callback)
318
- end
324
+ self.class.each_post_hook(error: error, &block)
319
325
 
320
326
  post_hooks.each do |hook|
321
327
  yield(hook.callback) if hook.always || !error
@@ -353,9 +359,9 @@ module Autobuild
353
359
  raise last_error
354
360
  else raise
355
361
  end
356
- rescue ::Exception => original_error
362
+ rescue ::Exception => e
357
363
  message = Autobuild.color('update failed', :red)
358
- last_error = original_error
364
+ last_error = e
359
365
  # If the package is patched, it might be that the update
360
366
  # failed because we needed to unpatch first. Try it out
361
367
  #
@@ -374,11 +380,11 @@ module Autobuild
374
380
  rescue Interrupt
375
381
  raise
376
382
  rescue ::Exception
377
- raise original_error
383
+ raise e
378
384
  end
379
385
  end
380
386
 
381
- retry_count = update_retry_count(original_error, retry_count)
387
+ retry_count = update_retry_count(e, retry_count)
382
388
  raise unless retry_count
383
389
 
384
390
  package.message "update failed in #{package.importdir}, "\
@@ -395,20 +401,20 @@ module Autobuild
395
401
  fallback(e, package, :import, package)
396
402
  end
397
403
 
398
- def perform_checkout(package, options = Hash.new)
404
+ def perform_checkout(package, **options)
399
405
  last_error = nil
400
406
  package.progress_start "checking out %s", :done_message => 'checked out %s' do
401
407
  retry_count = 0
402
408
  begin
403
- checkout(package, options)
409
+ checkout(package, **options)
404
410
  execute_post_hooks(package)
405
411
  rescue Interrupt
406
412
  if last_error then raise last_error
407
413
  else raise
408
414
  end
409
- rescue ::Exception => original_error
410
- last_error = original_error
411
- retry_count = update_retry_count(original_error, retry_count)
415
+ rescue ::Exception => e
416
+ last_error = e
417
+ retry_count = update_retry_count(e, retry_count)
412
418
  raise unless retry_count
413
419
 
414
420
  package.message "checkout of %s failed, "\
@@ -452,31 +458,26 @@ module Autobuild
452
458
  # ID is given will, in this mode, reset the repository to the requested ID
453
459
  # (if that does not involve losing commits). Otherwise, it will only
454
460
  # ensure that the requested commit ID is present in the current HEAD.
455
- def import(package, options = Hash.new)
461
+ def import( # rubocop:disable Metrics/ParameterLists
462
+ package, *old_boolean,
463
+ ignore_errors: false, checkout_only: false, allow_interactive: true, **options
464
+ )
456
465
  # Backward compatibility
457
- unless options.kind_of?(Hash)
458
- options = options
466
+ unless old_boolean.empty?
467
+ old_boolean = old_boolean.first
459
468
  Autoproj.warn "calling #import with a boolean as second argument "\
460
469
  "is deprecated, switch to the named argument interface instead"
461
- Autoproj.warn " e.g. call import(package, only_local: #{options})"
470
+ Autoproj.warn " e.g. call import(package, only_local: #{old_boolean})"
462
471
  Autoproj.warn " #{caller(1..1).first}"
463
- options = Hash[only_local: options]
472
+ options[:only_local] = old_boolean
464
473
  end
465
474
 
466
- options = Kernel.validate_options options,
467
- only_local: false,
468
- reset: false,
469
- checkout_only: false,
470
- ignore_errors: false,
471
- allow_interactive: true
472
- ignore_errors = options.delete(:ignore_errors)
473
-
474
475
  importdir = package.importdir
475
476
  if File.directory?(importdir)
476
477
  package.isolate_errors(mark_as_failed: false,
477
478
  ignore_errors: ignore_errors) do
478
- if !options[:checkout_only] && package.update?
479
- perform_update(package, options)
479
+ if !checkout_only && package.update?
480
+ perform_update(package, checkout_only: false, **options)
480
481
  elsif Autobuild.verbose
481
482
  package.message "%s: not updating"
482
483
  end
@@ -484,12 +485,11 @@ module Autobuild
484
485
 
485
486
  elsif File.exist?(importdir)
486
487
  raise ConfigException.new(package, 'import'),
487
- "#{importdir} exists but is not a directory"
488
+ "#{importdir} exists but is not a directory"
488
489
  else
489
490
  package.isolate_errors(mark_as_failed: true,
490
491
  ignore_errors: ignore_errors) do
491
- perform_checkout(package,
492
- allow_interactive: options[:allow_interactive])
492
+ perform_checkout(package, allow_interactive: allow_interactive)
493
493
  true
494
494
  end
495
495
  end
@@ -22,8 +22,11 @@ if Autobuild::HAS_RMAIL
22
22
  end
23
23
 
24
24
  attr_reader :from_email, :to_email, :smtp_hostname, :smtp_port,
25
- :subject, :only_errors
25
+ :subject, :only_errors
26
+
26
27
  def initialize(config)
28
+ super()
29
+
27
30
  @from_email = (config[:from] || default_mail)
28
31
  @to_email = (config[:to] || default_mail)
29
32
  @subject =
@@ -78,7 +81,7 @@ if Autobuild::HAS_RMAIL
78
81
  to_email.each do |email|
79
82
  mail.header.to = email
80
83
  smtp.send_mail(RMail::Serialize.write('', mail),
81
- from_email, email)
84
+ from_email, email)
82
85
  end
83
86
  end
84
87
 
@@ -64,7 +64,7 @@ module Autobuild
64
64
  # Some statistics about the commands that have been run
65
65
  attr_reader :statistics
66
66
 
67
- EnvOp = Struct.new :type, :name, :values
67
+ EnvOp = Struct.new :type, :name, :values # rubocop:disable Lint/StructNewOverride
68
68
 
69
69
  # List of environment values added by this package with {#env_add},
70
70
  # {#env_add_path} or {#env_set}
@@ -150,6 +150,7 @@ module Autobuild
150
150
  @imported = false
151
151
  @prepared = false
152
152
  @built = false
153
+ @disabled = nil
153
154
 
154
155
  if Hash === spec
155
156
  name, depends = spec.to_a.first
@@ -402,8 +403,8 @@ module Autobuild
402
403
  def isolate_errors(options = Hash.new)
403
404
  options = Hash[mark_as_failed: true] unless options.kind_of?(Hash)
404
405
  options = validate_options options,
405
- mark_as_failed: true,
406
- ignore_errors: Autobuild.ignore_errors
406
+ mark_as_failed: true,
407
+ ignore_errors: Autobuild.ignore_errors
407
408
 
408
409
  # Don't do anything if we already have failed
409
410
  if failed?
@@ -448,12 +449,12 @@ module Autobuild
448
449
  # be done there as well.
449
450
  #
450
451
  # (see Importer#import)
451
- def import(options = Hash.new)
452
- options = Hash[only_local: options] unless options.respond_to?(:to_hash)
452
+ def import(*old_boolean, **options)
453
+ options = { only_local: old_boolean.first } unless old_boolean.empty?
453
454
 
454
455
  @import_invoked = true
455
456
  if @importer
456
- result = @importer.import(self, options)
457
+ result = @importer.import(self, **options)
457
458
  elsif update?
458
459
  message "%s: no importer defined, doing nothing"
459
460
  end
@@ -495,12 +496,12 @@ module Autobuild
495
496
  end
496
497
  end
497
498
  if suffix.empty?
498
- return msg
499
+ msg
499
500
  elsif prefix_style.empty?
500
- return (prefix + suffix).join(" ")
501
+ (prefix + suffix).join(" ")
501
502
  else
502
503
  colorized_prefix = Autobuild.color(prefix.join(" "), *prefix_style)
503
- return [colorized_prefix, *suffix].join(" ")
504
+ [colorized_prefix, *suffix].join(" ")
504
505
  end
505
506
  end
506
507
 
@@ -527,7 +528,7 @@ module Autobuild
527
528
  args[0] = process_formatting_string(args[0], :bold)
528
529
  done_message = process_formatting_string(done_message) if done_message
529
530
  Autobuild.progress_start(self, *args,
530
- done_message: done_message, **raw_options, &block)
531
+ done_message: done_message, **raw_options, &block)
531
532
  end
532
533
 
533
534
  def progress(*args)
@@ -663,6 +664,10 @@ module Autobuild
663
664
  end
664
665
  end
665
666
 
667
+ def self_fingerprint
668
+ importer.fingerprint(self)
669
+ end
670
+
666
671
  # Returns a unique hash representing a state of the package and
667
672
  # its dependencies, if any dependency can't calculate its own
668
673
  # fingerprint the result will be nil
@@ -670,18 +675,23 @@ module Autobuild
670
675
  def fingerprint(recursive: true, memo: {})
671
676
  return memo[name] if memo.key?(name)
672
677
 
673
- self_fingerprint = importer.fingerprint(self)
678
+ self_fingerprint = self.self_fingerprint
674
679
  return unless self_fingerprint
675
- return self_fingerprint if !recursive || dependencies.empty?
680
+ if dependencies.empty?
681
+ return (memo[name] = self_fingerprint)
682
+ elsif !recursive
683
+ return self_fingerprint
684
+ end
676
685
 
677
686
  dependency_fingerprints = dependencies.sort.map do |pkg_name|
678
687
  pkg = Autobuild::Package[pkg_name]
679
688
  unless (fingerprint = memo[pkg.name])
680
689
  fingerprint = pkg.fingerprint(recursive: true, memo: memo)
681
- return unless fingerprint
690
+ break unless fingerprint
682
691
  end
683
692
  fingerprint
684
693
  end
694
+ return unless dependency_fingerprints
685
695
 
686
696
  memo[name] = Digest::SHA1.hexdigest(
687
697
  self_fingerprint + dependency_fingerprints.join(""))
@@ -829,7 +839,7 @@ module Autobuild
829
839
  end
830
840
 
831
841
  # Make sure that this package will be ignored in the build
832
- def disable(phases = Autobuild.all_phases)
842
+ def disable(_phases = Autobuild.all_phases)
833
843
  @disabled = true
834
844
  end
835
845
 
@@ -25,13 +25,8 @@ module Autobuild
25
25
  # To override this default behaviour on a per-package basis, use Autotools#use
26
26
  #
27
27
  class Autotools < Configurable
28
- attr_accessor :using
29
- attr_accessor :configureflags
30
- attr_accessor :aclocal_flags
31
- attr_accessor :autoheader_flags
32
- attr_accessor :autoconf_flags
33
- attr_accessor :automake_flags
34
- attr_accessor :bear_flags
28
+ attr_accessor :using, :configureflags, :aclocal_flags, :autoheader_flags,
29
+ :autoconf_flags, :automake_flags, :bear_flags
35
30
 
36
31
  @builddir = 'build'
37
32
  @@enable_bear_globally = false
@@ -151,7 +146,7 @@ module Autobuild
151
146
  FileUtils.rm_f configurestamp
152
147
  end
153
148
 
154
- def import(options = Hash.new)
149
+ def import(**options)
155
150
  # We force a regen after the first checkout. The issue is that
156
151
  # autotools is less robust than it should, and very often it is
157
152
  # better to generate the build system for the system on which we
@@ -278,7 +273,7 @@ module Autobuild
278
273
  file conffile => "#{conffile}#{confext}"
279
274
  elsif using[:autoconf]
280
275
  raise PackageException.new(self, 'prepare'),
281
- "neither configure.ac nor configure.in present in #{srcdir}"
276
+ "neither configure.ac nor configure.in present in #{srcdir}"
282
277
  end
283
278
 
284
279
  file conffile do