autoproj 2.9.0 → 2.10.0

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +113 -0
  3. data/.travis.yml +0 -2
  4. data/Gemfile +1 -0
  5. data/README.md +59 -14
  6. data/bin/autoproj_bootstrap +21 -12
  7. data/bin/autoproj_bootstrap.in +2 -2
  8. data/bin/autoproj_install +21 -12
  9. data/bin/autoproj_install.in +2 -2
  10. data/lib/autoproj/aruba_minitest.rb +4 -4
  11. data/lib/autoproj/autobuild_extensions/dsl.rb +91 -70
  12. data/lib/autoproj/autobuild_extensions/package.rb +20 -1
  13. data/lib/autoproj/build_option.rb +24 -7
  14. data/lib/autoproj/cli/base.rb +12 -1
  15. data/lib/autoproj/cli/bootstrap.rb +9 -3
  16. data/lib/autoproj/cli/build.rb +17 -13
  17. data/lib/autoproj/cli/envsh.rb +1 -1
  18. data/lib/autoproj/cli/exec.rb +5 -7
  19. data/lib/autoproj/cli/main.rb +44 -9
  20. data/lib/autoproj/cli/main_test.rb +2 -0
  21. data/lib/autoproj/cli/test.rb +29 -6
  22. data/lib/autoproj/cli/version.rb +52 -0
  23. data/lib/autoproj/cli/versions.rb +4 -1
  24. data/lib/autoproj/cli/watch.rb +2 -1
  25. data/lib/autoproj/configuration.rb +49 -11
  26. data/lib/autoproj/default.osdeps +9 -0
  27. data/lib/autoproj/manifest.rb +6 -6
  28. data/lib/autoproj/ops/build.rb +5 -15
  29. data/lib/autoproj/ops/import.rb +22 -3
  30. data/lib/autoproj/ops/install.rb +19 -10
  31. data/lib/autoproj/ops/main_config_switcher.rb +12 -6
  32. data/lib/autoproj/ops/snapshot.rb +5 -1
  33. data/lib/autoproj/os_package_resolver.rb +245 -209
  34. data/lib/autoproj/package_selection.rb +18 -0
  35. data/lib/autoproj/reporter.rb +45 -31
  36. data/lib/autoproj/test.rb +107 -56
  37. data/lib/autoproj/version.rb +1 -1
  38. data/lib/autoproj/workspace.rb +90 -72
  39. data/shell/completion/amake_bash +1 -0
  40. data/shell/completion/amake_zsh +1 -0
  41. data/shell/completion/autoproj_bash +2 -0
  42. data/shell/completion/autoproj_zsh +2 -0
  43. metadata +5 -3
@@ -1,7 +1,7 @@
1
1
  #! /usr/bin/ruby
2
2
 
3
- if RUBY_VERSION < "2.1.0"
4
- STDERR.puts "autoproj requires Ruby >= 2.1.0"
3
+ if RUBY_VERSION < "2.3.0"
4
+ STDERR.puts "autoproj requires Ruby >= 2.3.0"
5
5
  exit 1
6
6
  elsif ENV['AUTOPROJ_CURRENT_ROOT'] && (ENV['AUTOPROJ_CURRENT_ROOT'] != Dir.pwd)
7
7
  STDERR.puts "it seems that you've already loaded an env.sh script in this console, open a new console and try again"
@@ -25,8 +25,8 @@ def teardown
25
25
  super
26
26
  end
27
27
 
28
- def run_command_and_stop(*args, fail_on_error: true)
29
- cmd = run_command(*args)
28
+ def run_command_and_stop(*args, fail_on_error: true, **kwargs)
29
+ cmd = run_command(*args, **kwargs)
30
30
  cmd.stop
31
31
  if fail_on_error
32
32
  assert_command_finished_successfully(cmd)
@@ -34,8 +34,8 @@ def run_command_and_stop(*args, fail_on_error: true)
34
34
  cmd
35
35
  end
36
36
 
37
- def run_command(*args)
38
- @aruba_api.run(*args)
37
+ def run_command(*args, **kwargs)
38
+ @aruba_api.run_command(*args, **kwargs)
39
39
  end
40
40
 
41
41
  def chmod(*args) # also defined by Rake
@@ -32,22 +32,27 @@ def self.package_name_from_options(spec)
32
32
  end
33
33
  end
34
34
 
35
- # @deprecated use Autoproj.workspace.in_package_set or add a proper Loader object to your
36
- # class
35
+ # @deprecated use Autoproj.workspace.in_package_set or add a proper Loader
36
+ # object to your class
37
37
  def self.in_package_set(package_set, path, &block)
38
- Autoproj.warn_deprecated __method__, "use Autoproj.workspace.in_package_set instead"
38
+ Autoproj.warn_deprecated __method__,
39
+ "use Autoproj.workspace.in_package_set instead"
39
40
  Autoproj.workspace.in_package_set(package_set, path, &block)
40
41
  end
41
- # @deprecated use Autoproj.workspace.current_file or add a proper Loader object to your
42
- # class
42
+
43
+ # @deprecated use Autoproj.workspace.current_file or add a proper Loader
44
+ # object to your class
43
45
  def self.current_file
44
- Autoproj.warn_deprecated __method__, "use AUtoproj.workspace.current_file instead"
46
+ Autoproj.warn_deprecated __method__,
47
+ "use AUtoproj.workspace.current_file instead"
45
48
  Autoproj.workspace.current_file
46
49
  end
47
- # @deprecated use Autoproj.workspace.current_package_set or add a proper Loader object to your
48
- # class
50
+
51
+ # @deprecated use Autoproj.workspace.current_package_set or add a proper
52
+ # Loader object to your class
49
53
  def self.current_package_set
50
- Autoproj.warn_deprecated __method__, "use Autoproj.workspace.current_package_set instead"
54
+ Autoproj.warn_deprecated __method__,
55
+ "use Autoproj.workspace.current_package_set instead"
51
56
  Autoproj.workspace.current_package_set
52
57
  end
53
58
 
@@ -55,18 +60,22 @@ def self.current_package_set
55
60
  # Beware that the return value changed from Autobuild::Package to
56
61
  # Autoproj::PackageDefinition
57
62
  def self.define(package_type, spec, &block)
58
- Autoproj.warn_deprecated __method__, "use Autoproj.workspace.define_package instead (and beware that the return value changed from Autobuild::Package to Autoproj::PackageDefinition)"
63
+ Autoproj.warn_deprecated __method__, "use Autoproj.workspace.define_package "\
64
+ "instead (and beware that the return value changed from "\
65
+ "Autobuild::Package to Autoproj::PackageDefinition)"
59
66
  workspace.define_package(package_type, spec, block, *current_file).
60
67
  autobuild
61
68
  end
62
69
 
63
70
  def self.loaded_autobuild_files
64
- Autoproj.warn_deprecated __method__, "use Autoproj.workspace.loaded_autobuild_files"
71
+ Autoproj.warn_deprecated __method__,
72
+ "use Autoproj.workspace.loaded_autobuild_files"
65
73
  Autoproj.workspace.loaded_autobuild_files
66
74
  end
67
75
 
68
76
  def self.import_autobuild_file(package_set, path)
69
- Autoproj.warn_deprecated __method__, "use Autoproj.workspace.import_autobuild_file"
77
+ Autoproj.warn_deprecated __method__,
78
+ "use Autoproj.workspace.import_autobuild_file"
70
79
  Autoproj.workspace.import_autobuild_file(package_set, path)
71
80
  end
72
81
 
@@ -75,14 +84,11 @@ def self.find_topmost_directory_containing(dir, glob_pattern = nil)
75
84
  while dir != "/"
76
85
  match = false
77
86
  if glob_pattern
78
- if !Dir.glob(File.join(dir, glob_pattern)).empty?
79
- match = true
80
- end
87
+ match = true unless Dir.glob(File.join(dir, glob_pattern)).empty?
81
88
  end
82
89
 
83
- if !match && block_given? && yield(dir)
84
- match = true
85
- end
90
+ match = true if !match && block_given? && yield(dir)
91
+
86
92
  if !match && result
87
93
  return result
88
94
  elsif match
@@ -95,29 +101,42 @@ def self.find_topmost_directory_containing(dir, glob_pattern = nil)
95
101
 
96
102
  # Tries to find a handler automatically for 'full_path'
97
103
  def self.package_handler_for(full_path)
104
+ pyglob = File.join(File.basename(full_path), "*.py")
98
105
  if !Dir.enum_for(:glob, File.join(full_path, "*.orogen")).to_a.empty?
99
- return "orogen_package", full_path
106
+ ["orogen_package", full_path]
107
+ elsif File.file?(File.join(full_path, "Makefile.am"))
108
+ toplevel_dir = find_topmost_directory_containing(full_path) do |dir|
109
+ configure_ac = File.join(dir, 'configure.ac')
110
+ configure_in = File.join(dir, 'configure.in')
111
+ File.file?(configure_ac) || File.file?(configure_in)
112
+ end
113
+ ['autotools_package', toplevel_dir] if toplevel_dir
114
+ elsif File.file?(File.join(full_path, "configure.ac")) ||
115
+ File.file?(File.join(full_path, "configure.in"))
116
+ ['autotools_package', full_path]
100
117
  elsif File.file?(File.join(full_path, "CMakeLists.txt"))
101
118
  toplevel_dir = find_topmost_directory_containing(full_path) do |dir|
102
119
  cmakelists = File.join(dir, 'CMakeLists.txt')
103
120
  File.file?(cmakelists) &&
104
121
  (File.read(cmakelists) =~ /PROJECT/i)
105
122
  end
106
- toplevel_dir ||= find_topmost_directory_containing(full_path, 'CMakeLists.txt')
123
+ toplevel_dir ||= find_topmost_directory_containing(
124
+ full_path, 'CMakeLists.txt')
107
125
 
108
126
  manifest_xml = File.join(toplevel_dir, 'manifest.xml')
109
127
  package_xml = File.join(toplevel_dir, 'package.xml')
110
128
  if File.file?(package_xml) && !File.file?(manifest_xml)
111
129
  return "catkin_package", toplevel_dir
112
130
  end
113
- return "cmake_package", toplevel_dir
114
- elsif dir = find_topmost_directory_containing(full_path, "Rakefile") ||
115
- find_topmost_directory_containing(full_path, "lib/*.rb")
116
-
117
- return "ruby_package", dir
118
- elsif (dir = find_topmost_directory_containing(full_path, 'setup.py')) ||
119
- (dir = find_topmost_directory_containing(full_path, File.join(File.basename(full_path), "*.py")))
120
- return 'python_package', dir
131
+
132
+ ["cmake_package", toplevel_dir]
133
+ elsif (dir = (find_topmost_directory_containing(full_path, "Rakefile") ||
134
+ find_topmost_directory_containing(full_path, "lib/*.rb")))
135
+
136
+ ["ruby_package", dir]
137
+ elsif (dir = (find_topmost_directory_containing(full_path, 'setup.py') ||
138
+ find_topmost_directory_containing(full_path, pyglob)))
139
+ ['python_package', dir]
121
140
  end
122
141
  end
123
142
  end
@@ -130,9 +149,7 @@ def ignore(*paths)
130
149
 
131
150
  # Adds a new setup block to an existing package
132
151
  def setup_package(package_name, workspace: Autoproj.workspace, &block)
133
- if !block
134
- raise ConfigError.new, "you must give a block to #setup_package"
135
- end
152
+ raise ConfigError.new, "you must give a block to #setup_package" unless block
136
153
 
137
154
  package_definition = workspace.manifest.find_package_definition(package_name)
138
155
  if !package_definition
@@ -148,10 +165,11 @@ def setup_package(package_name, workspace: Autoproj.workspace, &block)
148
165
  def package_common(package_type, spec, workspace: Autoproj.workspace, &block)
149
166
  package_name = Autoproj.package_name_from_options(spec)
150
167
 
151
- if existing_package = workspace.manifest.find_package_definition(package_name)
168
+ if (existing_package = workspace.manifest.find_package_definition(package_name))
152
169
  current_file = workspace.current_file[1]
153
170
  old_file = existing_package.file
154
- Autoproj.warn "#{package_name} from #{current_file} is overridden by the definition in #{old_file}"
171
+ Autoproj.warn "#{package_name} from #{current_file} is overridden "\
172
+ "by the definition in #{old_file}"
155
173
  return existing_package.autobuild
156
174
  end
157
175
 
@@ -161,33 +179,33 @@ def package_common(package_type, spec, workspace: Autoproj.workspace, &block)
161
179
  end
162
180
 
163
181
  def import_package(name, workspace: Autoproj.workspace, &block)
164
- package_common(:import, name, workspace: Autoproj.workspace, &block)
182
+ package_common(:import, name, workspace: workspace, &block)
165
183
  end
166
184
 
167
- def python_package(name, workspace: Autoproj.workspace, &block)
168
- package_common(:python, name, workspace: Autoproj.workspace, &block)
185
+ def python_package(name, workspace: Autoproj.workspace)
186
+ package_common(:python, name, workspace: workspace) do |pkg|
187
+ pkg.internal_dependency 'python'
188
+ yield(pkg) if block_given?
189
+ end
169
190
  end
170
191
 
171
192
  def common_make_based_package_setup(pkg)
172
193
  unless pkg.has_doc? && pkg.doc_dir
173
194
  pkg.with_doc do
174
195
  doc_html = File.join(pkg.builddir, 'doc', 'html')
175
- if File.directory?(doc_html)
176
- pkg.doc_dir = doc_html
177
- end
196
+ pkg.doc_dir = doc_html if File.directory?(doc_html)
178
197
  end
179
198
  end
180
- if !pkg.test_utility.has_task?
181
- if !pkg.test_utility.source_dir
199
+
200
+ unless pkg.test_utility.has_task?
201
+ unless pkg.test_utility.source_dir
182
202
  test_dir = File.join(pkg.srcdir, 'test')
183
203
  if File.directory?(test_dir)
184
204
  pkg.test_utility.source_dir = File.join(pkg.builddir, 'test', 'results')
185
205
  end
186
206
  end
187
207
 
188
- if pkg.test_utility.source_dir
189
- pkg.with_tests
190
- end
208
+ pkg.with_tests if pkg.test_utility.source_dir
191
209
  end
192
210
  end
193
211
 
@@ -246,7 +264,6 @@ def env_add(name, value)
246
264
  Autoproj.env.add(name, value)
247
265
  end
248
266
 
249
-
250
267
  # Defines a Ruby package
251
268
  #
252
269
  # Example:
@@ -264,11 +281,10 @@ def ruby_package(name, workspace: Autoproj.workspace)
264
281
  # Documentation code. Ignore if the user provided its own documentation
265
282
  # task, or disabled the documentation generation altogether by setting
266
283
  # rake_doc_task to nil
267
- if !pkg.has_doc? && pkg.rake_doc_task
268
- pkg.with_doc
269
- end
270
- if !pkg.test_utility.has_task?
271
- if !pkg.test_utility.source_dir
284
+ pkg.with_doc if !pkg.has_doc? && pkg.rake_doc_task
285
+
286
+ unless pkg.test_utility.has_task?
287
+ unless pkg.test_utility.source_dir
272
288
  test_dir = File.join(pkg.srcdir, 'test')
273
289
  if File.directory?(test_dir)
274
290
  pkg.test_utility.source_dir = File.join(pkg.srcdir, '.test-results')
@@ -276,9 +292,7 @@ def ruby_package(name, workspace: Autoproj.workspace)
276
292
  end
277
293
  end
278
294
 
279
- if pkg.test_utility.source_dir
280
- pkg.with_tests
281
- end
295
+ pkg.with_tests if pkg.test_utility.source_dir
282
296
  end
283
297
 
284
298
  yield(pkg) if block_given?
@@ -318,13 +332,13 @@ def only_on(*architectures)
318
332
 
319
333
  os_names, os_versions = Autoproj.workspace.operating_system
320
334
  matching_archs = architectures.find_all { |arch| os_names.include?(arch[0].downcase) }
321
- if matching_archs.empty?
322
- return
323
- elsif matching_archs.none? { |arch| !arch[1] || os_versions.include?(arch[1].downcase) }
324
- return
335
+ return if matching_archs.empty?
336
+
337
+ has_matching_arch = matching_archs.any? do |arch|
338
+ !arch[1] || os_versions.include?(arch[1].downcase)
325
339
  end
326
340
 
327
- yield
341
+ yield if has_matching_arch
328
342
  end
329
343
 
330
344
  # Declare that the packages declared in the block should not be built in the
@@ -343,22 +357,25 @@ def not_on(*architectures)
343
357
 
344
358
  os_names, os_versions = Autoproj.workspace.operating_system
345
359
  matching_archs = architectures.find_all { |arch| os_names.include?(arch[0].downcase) }
346
- if matching_archs.empty?
347
- return yield
348
- elsif matching_archs.all? { |arch| arch[1] && !os_versions.include?(arch[1].downcase) }
349
- return yield
360
+ return yield if matching_archs.empty?
361
+
362
+ matches_arch = matching_archs.all? do |arch|
363
+ arch[1] && !os_versions.include?(arch[1].downcase)
350
364
  end
365
+ return yield if matches_arch
351
366
 
352
367
  # Simply get the current list of packages, yield the block, and exclude all
353
368
  # packages that have been added
354
369
  manifest = Autoproj.workspace.manifest
355
370
  current_packages = manifest.each_autobuild_package.map(&:name).to_set
356
371
  yield
357
- new_packages = manifest.each_autobuild_package.map(&:name).to_set -
372
+ new_packages =
373
+ manifest.each_autobuild_package.map(&:name).to_set -
358
374
  current_packages
359
375
 
360
376
  new_packages.each do |pkg_name|
361
- manifest.exclude_package(pkg_name, "#{pkg_name} is disabled on this operating system")
377
+ manifest.exclude_package(
378
+ pkg_name, "#{pkg_name} is disabled on this operating system")
362
379
  end
363
380
  end
364
381
 
@@ -366,7 +383,7 @@ def not_on(*architectures)
366
383
  # not built in any way
367
384
  def source_package(options, workspace: Autoproj.workspace)
368
385
  package_common(options, workspace: workspace) do |pkg|
369
- pkg.srcdir = pkg.name
386
+ pkg.srcdir = pkg.name
370
387
  yield(pkg) if block_given?
371
388
  end
372
389
  end
@@ -400,7 +417,7 @@ def package_enabled?(name)
400
417
 
401
418
  # If used in init.rb, allows to disable automatic imports from specific package
402
419
  # sets
403
- def disable_imports_from(name)
420
+ def disable_imports_from(_name)
404
421
  raise NotImplementedError, "not implemented in autoproj v2"
405
422
  end
406
423
 
@@ -448,12 +465,16 @@ def remove_from_default(*names)
448
465
  end
449
466
 
450
467
  def renamed_package(current_name, old_name, options)
451
- if options[:obsolete] && !Autoproj.workspace.manifest.explicitely_selected_in_layout?(old_name)
468
+ explicit_selection = Autoproj.workspace.manifest.
469
+ explicitely_selected_in_layout?(old_name)
470
+ if options[:obsolete] && !explicit_selection
452
471
  import_package old_name
453
- Autoproj.workspace.manifest.exclude_package old_name, "#{old_name} has been renamed to #{current_name}, you still have the option of using the old name by adding '- #{old_name}' explicitely in the layout in autoproj/manifest, but be warned that the name will stop being usable at all in the near future"
472
+ Autoproj.workspace.manifest.exclude_package old_name,
473
+ "#{old_name} has been renamed to #{current_name}, you still have "\
474
+ "the option of using the old name by adding '- #{old_name}' explicitely "\
475
+ "in the layout in autoproj/manifest, but be warned that the name will "\
476
+ "stop being usable at all in the near future"
454
477
  else
455
478
  metapackage old_name, current_name
456
479
  end
457
480
  end
458
-
459
-
@@ -3,7 +3,6 @@ module AutobuildExtensions
3
3
  module Package
4
4
  # Tags explicitely added with #add_tag
5
5
  attr_reader :added_tags
6
-
7
6
  attr_reader :optional_dependencies
8
7
 
9
8
  attr_reader :os_packages
@@ -24,6 +23,7 @@ def initialize(spec = Hash.new)
24
23
  @optional_dependencies = Set.new
25
24
  @description = PackageManifest.new(self, null: true)
26
25
  @use_package_xml = false
26
+ @internal_dependencies = []
27
27
  end
28
28
 
29
29
  # Whether we should use a package.xml file present in this package
@@ -34,6 +34,10 @@ def use_package_xml?
34
34
  @use_package_xml
35
35
  end
36
36
 
37
+ def internal_dependencies
38
+ @internal_dependencies.dup
39
+ end
40
+
37
41
  # Set {#use_package_xml?}
38
42
  attr_writer :use_package_xml
39
43
 
@@ -136,6 +140,21 @@ def remove_dependency(name)
136
140
  os_packages.delete name
137
141
  end
138
142
 
143
+ # @api private
144
+ #
145
+ # Adds and 'internal' dependency to the package
146
+ # 'Internal' dependencies are actually autobuild dependencies
147
+ # for a given package type. It is assumed that only
148
+ # osdeps that do not rely on strict package managers will be
149
+ # declared as internal dependencies.
150
+ #
151
+ # The difference between a regular "os dependency" is that
152
+ # the internal dependency is installed right after the impport
153
+ # phase (before the actual osdeps phase)
154
+ def internal_dependency(osdeps_name)
155
+ @internal_dependencies << osdeps_name
156
+ end
157
+
139
158
  def optional_dependency(name)
140
159
  optional_dependencies << name
141
160
  end
@@ -45,18 +45,35 @@ def doc
45
45
  end
46
46
  end
47
47
 
48
+ # Return either the current value if it is not nil, or use
49
+ # a default value
50
+ #
51
+ # @return [value, Boolean] Current value, and flag whether this is a
52
+ # default value
53
+ def ensure_value(current_value)
54
+ if !current_value.nil?
55
+ return current_value.to_s, false
56
+ elsif options[:default]
57
+ return options[:default].to_str, true
58
+ else
59
+ return '', true
60
+ end
61
+ end
62
+
63
+ # Ask the user for the setting of this option
64
+ # by providing the current value as input and falling
65
+ # back to default values if needed
66
+ #
67
+ # @param [String] current_value the option's current value
68
+ # @param [String] doc a string to override the default option banner
48
69
  def ask(current_value, doc = nil)
49
- default_value =
50
- if !current_value.nil? then current_value.to_s
51
- elsif options[:default] then options[:default].to_str
52
- else ''
53
- end
70
+ value,_ = ensure_value(current_value)
54
71
 
55
- STDOUT.print " #{doc || self.doc} [#{default_value}] "
72
+ STDOUT.print " #{doc || self.doc} [#{value}] "
56
73
  STDOUT.flush
57
74
  answer = STDIN.readline.chomp
58
75
  if answer == ''
59
- answer = default_value
76
+ answer = value
60
77
  end
61
78
  validate(answer)
62
79
 
@@ -156,9 +156,18 @@ def resolve_selection(user_selection, checkout_only: true, only_local: false, re
156
156
  raise CLIInvalidSelection, e.message, e.backtrace
157
157
  end
158
158
 
159
+ # Check whether the user selection refers to non-existant/unknown
160
+ # packages
161
+ #
162
+ # @param [Array<String>] user_selection List of selected packages
163
+ # @param [Autoproj::PackageSelection] resolved_selection The
164
+ # selection of known packages
165
+ # @raises [CLIInvalidArguments] if no match for a package could be found
159
166
  def validate_user_selection(user_selection, resolved_selection)
160
167
  not_matched = user_selection.find_all do |pkg_name|
161
- !resolved_selection.has_match_for?(pkg_name)
168
+ !resolved_selection.has_match_for?(pkg_name) &&
169
+ !(resolved_selection.ignored?(pkg_name) ||
170
+ resolved_selection.excluded?(pkg_name))
162
171
  end
163
172
  if !not_matched.empty?
164
173
  raise CLIInvalidArguments, "autoproj: wrong package selection on command line, cannot find a match for #{not_matched.to_a.sort.join(", ")}"
@@ -166,6 +175,8 @@ def validate_user_selection(user_selection, resolved_selection)
166
175
  end
167
176
 
168
177
  def validate_options(args, options)
178
+ interactive = options.delete(:interactive)
179
+ ws.config.interactive = interactive unless interactive.nil?
169
180
  self.class.validate_options(args, options)
170
181
  end
171
182