autoproj 2.9.0 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
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