autoproj 2.10.2 → 2.11.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.
@@ -30,6 +30,8 @@ def write_plugin_list(plugins)
30
30
  type: 'string', default: '>= 0'
31
31
  option :git, desc: 'checkout a git repository instead of downloading the gem',
32
32
  type: 'string'
33
+ option :branch, desc: 'choose the branch that should be checked out with --git',
34
+ type: 'string', default: 'master'
33
35
  option :path, desc: 'use the plugin that is already present on this path',
34
36
  type: 'string'
35
37
  def install(name)
@@ -40,6 +42,7 @@ def install(name)
40
42
  raise CLIInvalidArguments, "you can provide only one of --git or --path"
41
43
  elsif options[:git]
42
44
  gem_options[:git] = options[:git]
45
+ gem_options[:branch] = options[:branch]
43
46
  elsif options[:path]
44
47
  gem_options[:path] = options[:path]
45
48
  end
@@ -22,6 +22,21 @@ def report(report_options = Hash.new)
22
22
  end
23
23
  end
24
24
 
25
+ desc 'default [on|off]', 'set whether tests are enabled or disabled by default, without touching existing settings'
26
+ def default(on_or_off)
27
+ require 'autoproj/cli/test'
28
+ report(silent: true) do
29
+ cli = Test.new
30
+ args = cli.validate_options([], options)
31
+ enabled = case on_or_off
32
+ when 'on' then true
33
+ when 'off' then false
34
+ else raise ArgumentError, "expected 'on' or 'off'"
35
+ end
36
+ cli.default(enabled)
37
+ end
38
+ end
39
+
25
40
  desc 'enable [PACKAGES]', 'enable tests for the given packages (or for all packages if none are given)'
26
41
  option :deps, type: :boolean, default: false,
27
42
  desc: 'controls whether the dependencies of the packages given on the command line should be enabled as well (the default is not)'
@@ -1,92 +1,21 @@
1
- require 'autoproj/cli/inspection_tool'
1
+ require 'autoproj/cli/utility'
2
2
 
3
3
  module Autoproj
4
4
  module CLI
5
- class Test < InspectionTool
6
- def enable(user_selection, options = {})
7
- if user_selection.empty?
8
- ws.load_config
9
- ws.config.utility_enable_all('test')
10
- else
11
- initialize_and_load
12
- selection, = finalize_setup(
13
- user_selection,
14
- recursive: options[:deps],
15
- non_imported_packages: :return
16
- )
17
- ws.config.utility_enable('test', *selection)
18
- end
19
- ws.config.save
5
+ class Test < Utility
6
+ def initialize(ws = Workspace.default,
7
+ name: 'test',
8
+ report_path: ws.utility_report_path('test'))
9
+ super
20
10
  end
21
11
 
22
- def disable(user_selection, options = {})
23
- if user_selection.empty?
24
- ws.load_config
25
- ws.config.utility_disable_all('test')
26
- else
27
- initialize_and_load
28
- selection, = finalize_setup(
29
- user_selection,
30
- recursive: options[:deps],
31
- non_imported_packages: :return
32
- )
33
- ws.config.utility_disable('test', *selection)
34
- end
35
- ws.config.save
36
- end
37
-
38
- def list(user_selection, options = {})
39
- initialize_and_load
40
- resolved_selection, = finalize_setup(
41
- user_selection,
42
- recursive: options[:deps],
43
- non_imported_packages: :return
44
- )
45
-
46
- lines = []
47
- resolved_selection.each do |pkg_name|
48
- pkg = ws.manifest.find_package_definition(pkg_name).autobuild
49
- lines << [
50
- pkg.name,
51
- pkg.test_utility.enabled?,
52
- pkg.test_utility.available?
53
- ]
54
- end
55
- lines = lines.sort_by { |name, _| name }
56
- w = lines.map { |name, _| name.length }.max
57
- out_format = "%-#{w}s %-7s %-9s"
58
- puts format(out_format, 'Package Name', 'Enabled', 'Available')
59
- lines.each do |name, enabled, available|
60
- puts(format(out_format, name, (!!enabled).to_s, (!!available).to_s))
61
- end
62
- end
63
-
64
- def run(user_selection, options = {})
65
- options[:parallel] ||= ws.config.parallel_build_level
66
- initialize_and_load
67
-
68
- packages, _, resolved_selection = finalize_setup(
69
- user_selection,
70
- recursive: user_selection.empty? || options[:deps]
71
- )
72
-
73
- validate_user_selection(user_selection, resolved_selection)
74
- if packages.empty?
75
- raise CLIInvalidArguments, "autoproj: the provided package "\
76
- "is not selected for build"
77
- end
78
-
79
- packages.each do |pkg|
80
- ws.manifest.find_autobuild_package(pkg).disable_phases(
81
- 'import', 'prepare', 'install'
82
- )
83
- end
84
-
85
- Autobuild.apply(
86
- packages,
87
- 'autoproj-test',
88
- ['test'],
89
- parallel: options[:parallel]
12
+ def package_metadata(package)
13
+ u = package.autobuild.test_utility
14
+ super.merge(
15
+ 'coverage_available' => !!u.coverage_available?,
16
+ 'coverage_enabled' => !!u.coverage_enabled?,
17
+ 'coverage_source_dir' => u.coverage_source_dir,
18
+ 'coverage_target_dir' => u.coverage_target_dir
90
19
  )
91
20
  end
92
21
  end
@@ -66,7 +66,7 @@ def validate_options(selection, options)
66
66
  return selection, options
67
67
  end
68
68
 
69
- def run(selected_packages, run_hook: false, **options)
69
+ def run(selected_packages, run_hook: false, report: true, **options)
70
70
  ws.manifest.accept_unavailable_osdeps = !options[:osdeps]
71
71
  ws.setup
72
72
  ws.autodetect_operating_system(force: true)
@@ -121,7 +121,8 @@ def run(selected_packages, run_hook: false, **options)
121
121
  keep_going: options[:keep_going],
122
122
  parallel: options[:parallel] || ws.config.parallel_import_level,
123
123
  retry_count: options[:retry_count],
124
- auto_exclude: options[:auto_exclude])
124
+ auto_exclude: options[:auto_exclude],
125
+ report: report)
125
126
 
126
127
  ws.finalize_setup
127
128
  ws.export_installation_manifest
@@ -195,13 +196,15 @@ def normalize_osdeps_options(
195
196
  def update_packages(selected_packages,
196
197
  from: nil, checkout_only: false, only_local: false, reset: false,
197
198
  deps: true, keep_going: false, parallel: 1,
198
- retry_count: 0, osdeps: true, auto_exclude: false, osdeps_options: Hash.new)
199
+ retry_count: 0, osdeps: true, auto_exclude: false, osdeps_options: Hash.new,
200
+ report: true)
199
201
 
200
202
  if from
201
203
  setup_update_from(from)
202
204
  end
203
205
 
204
- ops = Autoproj::Ops::Import.new(ws)
206
+ ops = Autoproj::Ops::Import.new(
207
+ ws, report_path: (ws.import_report_path if report))
205
208
  source_packages, osdep_packages =
206
209
  ops.import_packages(selected_packages,
207
210
  checkout_only: checkout_only,
@@ -0,0 +1,139 @@
1
+ require 'autoproj/cli/inspection_tool'
2
+
3
+ module Autoproj
4
+ module CLI
5
+ class Utility < InspectionTool
6
+ def initialize(ws, name: nil, report_path: nil)
7
+ @utility_name = name
8
+ @report_path = report_path
9
+ super(ws)
10
+ end
11
+
12
+ attr_reader :utility_name
13
+ def default(enabled)
14
+ ws.load_config
15
+ ws.config.utility_default(utility_name, enabled)
16
+ ws.config.save
17
+ end
18
+
19
+ def enable(user_selection, options = {})
20
+ if user_selection.empty?
21
+ ws.load_config
22
+ ws.config.utility_enable_all(utility_name)
23
+ else
24
+ initialize_and_load
25
+ selection, = finalize_setup(
26
+ user_selection,
27
+ recursive: options[:deps],
28
+ non_imported_packages: :return
29
+ )
30
+ ws.config.utility_enable(utility_name, *selection)
31
+ end
32
+ ws.config.save
33
+ end
34
+
35
+ def disable(user_selection, options = {})
36
+ if user_selection.empty?
37
+ ws.load_config
38
+ ws.config.utility_disable_all(utility_name)
39
+ else
40
+ initialize_and_load
41
+ selection, = finalize_setup(
42
+ user_selection,
43
+ recursive: options[:deps],
44
+ non_imported_packages: :return
45
+ )
46
+ ws.config.utility_disable(utility_name, *selection)
47
+ end
48
+ ws.config.save
49
+ end
50
+
51
+ def list(user_selection, options = {})
52
+ initialize_and_load
53
+ resolved_selection, = finalize_setup(
54
+ user_selection,
55
+ recursive: options[:deps],
56
+ non_imported_packages: :return
57
+ )
58
+
59
+ lines = []
60
+ resolved_selection.each do |pkg_name|
61
+ pkg = ws.manifest.find_package_definition(pkg_name).autobuild
62
+ lines << [
63
+ pkg.name,
64
+ pkg.send("#{utility_name}_utility").enabled?,
65
+ pkg.send("#{utility_name}_utility").available?
66
+ ]
67
+ end
68
+ lines = lines.sort_by { |name, _| name }
69
+ w = lines.map { |name, _| name.length }.max
70
+ out_format = "%-#{w}s %-7s %-9s"
71
+ puts format(out_format, 'Package Name', 'Enabled', 'Available')
72
+ lines.each do |name, enabled, available|
73
+ puts(format(out_format, name, (!!enabled).to_s, (!!available).to_s))
74
+ end
75
+ end
76
+
77
+ def run(user_selection, options = {})
78
+ options[:parallel] ||= ws.config.parallel_build_level
79
+ initialize_and_load
80
+
81
+ user_selection, = normalize_command_line_package_selection(user_selection)
82
+ package_names, _, resolved_selection = finalize_setup(
83
+ user_selection,
84
+ recursive: user_selection.empty? || options[:deps]
85
+ )
86
+
87
+ validate_user_selection(user_selection, resolved_selection)
88
+ if package_names.empty?
89
+ raise CLIInvalidArguments, "autoproj: the provided package "\
90
+ "is not selected for build"
91
+ end
92
+
93
+ packages = package_names.map do |pkg_name|
94
+ ws.manifest.find_package_definition(pkg_name)
95
+ end
96
+
97
+ Autobuild.apply(
98
+ package_names,
99
+ "autoproj-#{utility_name}",
100
+ [utility_name],
101
+ parallel: options[:parallel]
102
+ )
103
+
104
+ ensure
105
+ create_report(packages) if packages && @report_path
106
+ end
107
+
108
+ def package_metadata(package)
109
+ u = package.autobuild.utility(@utility_name)
110
+ {
111
+ 'source_dir' => u.source_dir,
112
+ 'target_dir' => u.target_dir,
113
+ 'available' => !!u.available?,
114
+ 'enabled' => !!u.enabled?,
115
+ 'invoked' => !!u.invoked?,
116
+ 'success' => !!u.success?,
117
+ 'installed' => !!u.installed?,
118
+ }
119
+ end
120
+
121
+ def create_report(packages)
122
+ info = packages.each_with_object({}) do |p, map|
123
+ map[p.name] = package_metadata(p)
124
+ end
125
+
126
+ FileUtils.mkdir_p File.dirname(@report_path)
127
+ File.open(@report_path, 'w') do |io|
128
+ dump = JSON.dump(
129
+ "#{@utility_name}_report" => {
130
+ 'timestamp' => Time.now,
131
+ 'packages' => info
132
+ }
133
+ )
134
+ io.write dump
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -506,6 +506,19 @@ def utility_enabled_for?(utility, package)
506
506
  end
507
507
  end
508
508
 
509
+ # Set the given utility to enabled by default
510
+ #
511
+ # Unlike {#utility_enable_all} and {#utility_disable_all}, it does
512
+ # not touch existing exclusions
513
+ #
514
+ # @param [String] utility the utility name (e.g. 'doc' or 'test')
515
+ # @param [Boolean] enabled whether the utility will be enabled (true) or
516
+ # disabled (false)
517
+ # @return [void]
518
+ def utility_default(utility, enabled)
519
+ set("#{utility_key(utility)}_default", enabled ? true : false)
520
+ end
521
+
509
522
  # Enables a utility for all packages
510
523
  #
511
524
  # This both sets the default value for all packages and resets all
@@ -171,6 +171,13 @@ python:
171
171
  opensuse: python-devel
172
172
  default: ignore # will be installed manually by the user
173
173
 
174
+ python-setuptools:
175
+ arch: python2-distribute
176
+ debian,ubuntu: python-setuptools
177
+ fedora: python-setuptools
178
+ gentoo: dev-python/setuptools
179
+ default: ignore # will be installed manually by the user
180
+
174
181
  sudo:
175
182
  macos-brew: ignore
176
183
  default: sudo
@@ -1020,23 +1020,14 @@ def load_package_manifest(pkg)
1020
1020
  if manifest
1021
1021
  pkg.autobuild.description = manifest
1022
1022
  else
1023
- Autoproj.warn "#{package.name} from #{package_set.name} does not have a manifest"
1023
+ Autoproj.warn "#{package.name} from #{package_set.name} "\
1024
+ "does not have a manifest"
1024
1025
  end
1025
1026
 
1026
- manifest = pkg.autobuild.description
1027
- manifest.each_dependency(pkg.modes) do |name, is_optional|
1028
- begin
1029
- if is_optional
1030
- package.optional_dependency name
1031
- else
1032
- package.depends_on name
1033
- end
1034
- rescue ConfigError => e
1035
- raise ConfigError.new(manifest_path),
1036
- "manifest #{manifest_path} of #{package.name} from #{package_set.name} lists '#{name}' as dependency, but it is neither a normal package nor an osdeps package. osdeps reports: #{e.message}", e.backtrace
1037
- end
1038
- end
1039
- manifest
1027
+ pkg.apply_dependencies_from_manifest
1028
+ # #description is initialized with a null package manifest
1029
+ # return it even if we haven't overriden it
1030
+ pkg.autobuild.description
1040
1031
  end
1041
1032
 
1042
1033
  def load_all_available_package_manifests
@@ -92,35 +92,29 @@ def build_packages(all_enabled_packages, options = Hash.new)
92
92
  begin
93
93
  Autobuild.apply(all_enabled_packages, "autoproj-build", ['build'], options)
94
94
  ensure
95
- build_report(all_enabled_packages) if @report_path
95
+ create_report(all_enabled_packages) if @report_path
96
96
  end
97
97
  end
98
98
 
99
- def build_report(package_list)
99
+ def create_report(package_list)
100
100
  FileUtils.mkdir_p File.dirname(@report_path)
101
101
 
102
- packages = package_list.map do |pkg_name|
102
+ packages = package_list.each_with_object({}) do |pkg_name, h|
103
103
  pkg = manifest.find_autobuild_package(pkg_name)
104
104
 
105
- {
106
- name: pkg.name,
107
- import_invoked: pkg.import_invoked?,
108
- prepare_invoked: pkg.prepare_invoked?,
109
- build_invoked: pkg.build_invoked?,
110
- failed: pkg.failed?,
111
- imported: pkg.imported?,
112
- prepared: pkg.prepared?,
113
- built: pkg.built?
105
+ h[pkg.name] = {
106
+ invoked: !!pkg.install_invoked?,
107
+ success: !!pkg.installed?
114
108
  }
115
109
  end
116
110
 
117
- build_report = JSON.pretty_generate({
111
+ report = JSON.pretty_generate({
118
112
  build_report: {
119
113
  timestamp: Time.now,
120
114
  packages: packages
121
115
  }
122
116
  })
123
- IO.write(@report_path, build_report)
117
+ IO.write(@report_path, report)
124
118
  end
125
119
  end
126
120
  end
@@ -12,9 +12,10 @@ def auto_exclude?
12
12
  end
13
13
  attr_writer :auto_exclude
14
14
 
15
- def initialize(ws)
15
+ def initialize(ws, report_path: nil)
16
16
  @ws = ws
17
17
  @auto_exclude = false
18
+ @report_path = report_path
18
19
  end
19
20
 
20
21
  def mark_exclusion_along_revdeps(pkg_name, revdeps, chain = [], reason = nil)
@@ -22,24 +23,24 @@ def mark_exclusion_along_revdeps(pkg_name, revdeps, chain = [], reason = nil)
22
23
  chain.unshift pkg_name
23
24
  if root
24
25
  reason = ws.manifest.exclusion_reason(pkg_name)
26
+ elsif chain.size == 1
27
+ ws.manifest.exclude_package(pkg_name, "its dependency #{reason}")
25
28
  else
26
- if chain.size == 1
27
- ws.manifest.exclude_package(pkg_name, "its dependency #{reason}")
28
- else
29
- ws.manifest.exclude_package(pkg_name, "#{reason} (dependency chain: #{chain.join(">")})")
30
- end
29
+ ws.manifest.exclude_package(pkg_name, "#{reason} (dependency chain: "\
30
+ "#{chain.join('>')})")
31
31
  end
32
32
 
33
- return if !revdeps.has_key?(pkg_name)
33
+ return unless revdeps.key?(pkg_name)
34
+
34
35
  revdeps[pkg_name].each do |dep_name|
35
- if !ws.manifest.excluded?(dep_name)
36
+ unless ws.manifest.excluded?(dep_name)
36
37
  mark_exclusion_along_revdeps(dep_name, revdeps, chain.dup, reason)
37
38
  end
38
39
  end
39
40
  end
40
41
 
41
42
  VALID_OSDEP_AVAILABILITY =
42
- [OSPackageResolver::AVAILABLE, OSPackageResolver::IGNORE]
43
+ [OSPackageResolver::AVAILABLE, OSPackageResolver::IGNORE].freeze
43
44
 
44
45
  def import_next_step(pkg, reverse_dependencies)
45
46
  new_packages = []
@@ -85,23 +86,32 @@ def pre_package_import(selection, manifest, pkg, reverse_dependencies)
85
86
  elsif manifest.ignored?(pkg.name)
86
87
  false
87
88
  elsif !pkg.importer && !File.directory?(pkg.srcdir)
88
- raise ConfigError.new, "#{pkg.name} has no VCS, but is not checked out in #{pkg.srcdir}"
89
+ raise ConfigError.new, "#{pkg.name} has no VCS, but is not "\
90
+ "checked out in #{pkg.srcdir}"
89
91
  else
90
92
  true
91
93
  end
92
94
  end
93
95
 
94
- def post_package_import(selection, manifest, pkg, reverse_dependencies, auto_exclude: auto_exclude?)
95
- Rake::Task["#{pkg.name}-import"].instance_variable_set(:@already_invoked, true)
96
+ def post_package_import(selection, manifest, pkg, reverse_dependencies,
97
+ auto_exclude: auto_exclude?)
98
+ Rake::Task["#{pkg.name}-import"]
99
+ .instance_variable_set(:@already_invoked, true)
96
100
  if pkg.checked_out?
97
101
  begin
98
102
  manifest.load_package_manifest(pkg.name)
99
- rescue Exception => e
100
- raise if !auto_exclude
101
- manifest.add_exclusion(pkg.name, "#{pkg.name} failed to import with #{e} and auto_exclude was true")
103
+ rescue StandardError => e
104
+ raise unless auto_exclude
105
+
106
+ manifest.add_exclusion(pkg.name, "#{pkg.name} failed to import "\
107
+ "with #{e} and auto_exclude was true")
102
108
  end
103
109
  end
104
110
 
111
+ if !manifest.excluded?(pkg.name) && !manifest.ignored?(pkg.name)
112
+ process_post_import_blocks(pkg) if pkg.checked_out?
113
+ end
114
+
105
115
  # The package setup mechanisms might have added an exclusion
106
116
  # on this package. Handle this.
107
117
  if manifest.excluded?(pkg.name)
@@ -113,10 +123,8 @@ def post_package_import(selection, manifest, pkg, reverse_dependencies, auto_exc
113
123
  elsif manifest.ignored?(pkg.name)
114
124
  false
115
125
  else
116
- if pkg.checked_out?
117
- process_post_import_blocks(pkg)
118
- end
119
- import_next_step(pkg, reverse_dependencies)
126
+ pkg.apply_dependencies_from_manifest
127
+ import_next_step(pkg.autobuild, reverse_dependencies)
120
128
  end
121
129
  end
122
130
 
@@ -163,16 +171,16 @@ def install_internal_dependencies_for(*packages, **osdeps_options)
163
171
  # @param [Integer] retry_count the number of retries that are
164
172
  # allowed. Set to zero for no retry
165
173
  # @param [Hash] import_options options passed to {Autobuild::Importer#import}
166
- def queue_import_work(executor, completion_queue, pkg, retry_count: nil, **import_options)
167
- import_future = Concurrent::Future.new(executor: executor, args: [pkg]) do |import_pkg|
174
+ def queue_import_work(executor, completion_queue, pkg,
175
+ retry_count: nil, **import_options)
176
+ import_future = Concurrent::Future
177
+ .new(executor: executor, args: [pkg]) do |import_pkg|
168
178
  ## COMPLETELY BYPASS RAKE HERE
169
179
  # The reason is that the ordering of import/prepare between
170
180
  # packages is not important BUT the ordering of import vs.
171
181
  # prepare in one package IS important: prepare is the method
172
182
  # that takes into account dependencies.
173
- if retry_count
174
- import_pkg.autobuild.importer.retry_count = retry_count
175
- end
183
+ import_pkg.autobuild.importer.retry_count = retry_count if retry_count
176
184
  import_pkg.autobuild.import(**import_options)
177
185
  end
178
186
  import_future.add_observer do |time, result, reason|
@@ -193,8 +201,10 @@ def import_selected_packages(selection,
193
201
  auto_exclude: auto_exclude?,
194
202
  **import_options)
195
203
 
196
- if ![:checkout, :ignore, :return].include?(non_imported_packages)
197
- raise ArgumentError, "invalid value for 'non_imported_packages'. Expected one of :checkout, :ignore or :return but got #{non_imported_packages}"
204
+ unless %i[checkout ignore return].include?(non_imported_packages)
205
+ raise ArgumentError, "invalid value for 'non_imported_packages'. "\
206
+ "Expected one of :checkout, :ignore or :return "\
207
+ "but got #{non_imported_packages}"
198
208
  end
199
209
 
200
210
  # This is used in the ensure block, initialize as early as
@@ -220,6 +230,7 @@ def import_selected_packages(selection,
220
230
  all_processed_packages = Set.new
221
231
  main_thread_imports = Array.new
222
232
  package_queue = selected_packages.to_a.sort_by(&:name)
233
+
223
234
  failures = Array.new
224
235
  missing_vcs = Array.new
225
236
  installed_vcs_packages = Set['none', 'local']
@@ -228,24 +239,25 @@ def import_selected_packages(selection,
228
239
  package_queue.each do |pkg|
229
240
  # Remove packages that have already been processed
230
241
  next if all_processed_packages.include?(pkg)
231
- if (non_imported_packages != :checkout) && !File.directory?(pkg.autobuild.srcdir)
242
+
243
+ vcs_installed = installed_vcs_packages.include?(pkg.vcs.type)
244
+ if (non_imported_packages != :checkout) && !pkg.checked_out?
245
+ all_processed_packages << pkg
232
246
  if non_imported_packages == :return
233
- all_processed_packages << pkg
234
247
  completion_queue << [pkg, Time.now, false, nil]
235
- next
236
248
  else
237
- all_processed_packages << pkg
238
249
  ws.manifest.ignore_package(pkg.name)
239
- next
240
250
  end
241
- elsif install_vcs_packages && !installed_vcs_packages.include?(pkg.vcs.type)
251
+ next
252
+ elsif install_vcs_packages && !vcs_installed
242
253
  missing_vcs << pkg
243
254
  next
244
255
  end
245
256
  all_processed_packages << pkg
246
257
 
247
258
  importer = pkg.autobuild.importer
248
- if !pre_package_import(selection, manifest, pkg.autobuild, reverse_dependencies)
259
+ if !pre_package_import(selection, manifest, pkg.autobuild,
260
+ reverse_dependencies)
249
261
  next
250
262
  elsif !importer
251
263
  # The validity of this is checked in
@@ -255,7 +267,7 @@ def import_selected_packages(selection,
255
267
  elsif importer.interactive?
256
268
  main_thread_imports << pkg
257
269
  next
258
- elsif pkg.autobuild.checked_out? && import_options[:checkout_only]
270
+ elsif pkg.checked_out? && import_options[:checkout_only]
259
271
  main_thread_imports << pkg
260
272
  next
261
273
  end
@@ -263,20 +275,21 @@ def import_selected_packages(selection,
263
275
  pending_packages << pkg
264
276
  begin
265
277
  queue_import_work(
266
- executor, completion_queue, pkg, retry_count: retry_count,
278
+ executor, completion_queue, pkg,
279
+ retry_count: retry_count,
267
280
  **import_options.merge(allow_interactive: false))
268
281
  rescue Exception
269
282
  pending_packages.delete(pkg)
270
283
  raise
271
284
  end
272
- true
273
285
  end
274
286
  package_queue.clear
275
287
 
276
288
  if completion_queue.empty? && pending_packages.empty?
277
- if !missing_vcs.empty?
289
+ unless missing_vcs.empty?
278
290
  installed_vcs_packages.merge(
279
- install_vcs_packages_for(*missing_vcs, **install_vcs_packages))
291
+ install_vcs_packages_for(*missing_vcs,
292
+ **install_vcs_packages))
280
293
  package_queue.concat(missing_vcs)
281
294
  missing_vcs.clear
282
295
  next
@@ -289,15 +302,17 @@ def import_selected_packages(selection,
289
302
  break
290
303
  else
291
304
  main_thread_imports.delete_if do |pkg|
305
+ # rubocop:disable Lint/HandleExceptions
292
306
  begin
293
307
  if retry_count
294
308
  pkg.autobuild.importer.retry_count = retry_count
295
309
  end
296
310
  result = pkg.autobuild.import(
297
311
  **import_options.merge(allow_interactive: true))
298
- rescue Exception => reason
312
+ rescue StandardError => e
299
313
  end
300
- completion_queue << [pkg, Time.now, result, reason]
314
+ completion_queue << [pkg, Time.now, result, e]
315
+ # rubocop:enable Lint/HandleExceptions
301
316
  end
302
317
  end
303
318
  end
@@ -309,20 +324,21 @@ def import_selected_packages(selection,
309
324
  if reason.kind_of?(Autobuild::InteractionRequired)
310
325
  main_thread_imports << pkg
311
326
  elsif auto_exclude
312
- manifest.add_exclusion(pkg.name, "#{pkg.name} failed to import with #{reason} and auto_exclude was true")
327
+ manifest.add_exclusion(
328
+ pkg.name, "#{pkg.name} failed to import with "\
329
+ "#{reason} and auto_exclude was true")
313
330
  selection.filter_excluded_and_ignored_packages(manifest)
314
331
  else
315
332
  # One importer failed... terminate
316
333
  Autoproj.error "import of #{pkg.name} failed"
317
- if !reason.kind_of?(Interrupt)
318
- Autoproj.error "#{reason}"
319
- end
334
+ Autoproj.error reason.to_s unless reason.kind_of?(Interrupt)
320
335
  failures << reason
321
336
  end
322
337
  else
323
- if new_packages = post_package_import(
324
- selection, manifest, pkg.autobuild, reverse_dependencies,
325
- auto_exclude: auto_exclude)
338
+ new_packages = post_package_import(
339
+ selection, manifest, pkg, reverse_dependencies,
340
+ auto_exclude: auto_exclude)
341
+ if new_packages
326
342
  # Excluded dependencies might have caused the package to be
327
343
  # excluded as well ... do not add any dependency to the
328
344
  # processing queue if it is the case
@@ -336,10 +352,10 @@ def import_selected_packages(selection,
336
352
  end
337
353
 
338
354
  all_processed_packages.delete_if do |processed_pkg|
339
- ws.manifest.excluded?(processed_pkg.name) || ws.manifest.ignored?(processed_pkg.name)
355
+ ws.manifest.excluded?(processed_pkg.name) ||
356
+ ws.manifest.ignored?(processed_pkg.name)
340
357
  end
341
- return all_processed_packages, failures
342
-
358
+ [all_processed_packages, failures]
343
359
  ensure
344
360
  if failures && !failures.empty? && !keep_going
345
361
  Autoproj.error "waiting for pending import jobs to finish"
@@ -354,13 +370,16 @@ def finalize_package_load(processed_packages, auto_exclude: auto_exclude?)
354
370
  manifest = ws.manifest
355
371
 
356
372
  all = Set.new
357
- package_queue = manifest.all_layout_packages(false).each_source_package_name.to_a +
373
+ package_queue =
374
+ manifest.all_layout_packages(false)
375
+ .each_source_package_name.to_a +
358
376
  processed_packages.map(&:name).to_a
359
- while !package_queue.empty?
377
+
378
+ until package_queue.empty?
360
379
  pkg_name = package_queue.shift
361
380
  next if all.include?(pkg_name)
362
- all << pkg_name
363
381
 
382
+ all << pkg_name
364
383
  next if manifest.ignored?(pkg_name) || manifest.excluded?(pkg_name)
365
384
 
366
385
  pkg_definition = manifest.find_package_definition(pkg_name)
@@ -370,27 +389,28 @@ def finalize_package_load(processed_packages, auto_exclude: auto_exclude?)
370
389
  manifest.load_package_manifest(pkg.name)
371
390
  process_post_import_blocks(pkg)
372
391
  rescue Exception => e
373
- raise if !auto_exclude
374
- manifest.exclude_package(pkg.name, "#{pkg.name} had an error when being loaded (#{e.message}) and auto_exclude is true")
392
+ raise unless auto_exclude
393
+
394
+ manifest.exclude_package(
395
+ pkg.name, "#{pkg.name} had an error when "\
396
+ "being loaded (#{e.message}) and "\
397
+ "auto_exclude is true")
375
398
  next
376
399
  end
377
400
  end
378
401
 
379
402
  packages, osdeps = pkg.partition_optional_dependencies
380
- packages.each do |dep_pkg_name|
381
- if !manifest.ignored?(dep_pkg_name) && !manifest.excluded?(dep_pkg_name)
382
- pkg.depends_on dep_pkg_name
383
- end
384
- end
385
- osdeps.each do |osdep_pkg_name|
386
- if !manifest.ignored?(osdep_pkg_name) && !manifest.excluded?(osdep_pkg_name)
387
- pkg.os_packages << osdep_pkg_name
388
- end
403
+ (packages + osdeps).each do |dep_pkg_name|
404
+ next if manifest.ignored?(dep_pkg_name)
405
+ next if manifest.excluded?(dep_pkg_name)
406
+
407
+ pkg.depends_on dep_pkg_name
389
408
  end
390
409
 
391
410
  if File.directory?(pkg.srcdir)
392
411
  pkg.prepare
393
- Rake::Task["#{pkg.name}-prepare"].instance_variable_set(:@already_invoked, true)
412
+ Rake::Task["#{pkg.name}-prepare"]
413
+ .instance_variable_set(:@already_invoked, true)
394
414
  end
395
415
  pkg.update_environment
396
416
  package_queue.concat(pkg.dependencies)
@@ -419,9 +439,7 @@ def import_packages(selection,
419
439
  auto_exclude: auto_exclude,
420
440
  **import_options)
421
441
 
422
- if !keep_going && !failures.empty?
423
- raise failures.first
424
- end
442
+ raise failures.first if !keep_going && !failures.empty?
425
443
 
426
444
  install_internal_dependencies_for(*all_processed_packages)
427
445
  finalize_package_load(all_processed_packages, auto_exclude: auto_exclude)
@@ -437,14 +455,17 @@ def import_packages(selection,
437
455
  if warn_about_excluded_packages
438
456
  selection.exclusions.each do |sel, pkg_names|
439
457
  pkg_names.sort.each do |pkg_name|
440
- Autoproj.warn "#{pkg_name}, which was selected for #{sel}, cannot be built: #{manifest.exclusion_reason(pkg_name)}", :bold
458
+ Autoproj.warn "#{pkg_name}, which was selected "\
459
+ "for #{sel}, cannot be built: "\
460
+ "#{manifest.exclusion_reason(pkg_name)}", :bold
441
461
  end
442
462
  end
443
463
  end
444
464
  if warn_about_ignored_packages
445
465
  selection.ignores.each do |sel, pkg_names|
446
466
  pkg_names.sort.each do |pkg_name|
447
- Autoproj.warn "#{pkg_name}, which was selected for #{sel}, is ignored", :bold
467
+ Autoproj.warn "#{pkg_name}, which was selected for #{sel}, "\
468
+ "is ignored", :bold
448
469
  end
449
470
  end
450
471
  end
@@ -452,41 +473,67 @@ def import_packages(selection,
452
473
  if !failures.empty?
453
474
  raise PackageImportFailed.new(
454
475
  failures, source_packages: all_enabled_sources,
455
- osdep_packages: all_enabled_osdeps)
476
+ osdep_packages: all_enabled_osdeps)
456
477
  else
457
478
  return all_enabled_sources, all_enabled_osdeps
458
479
  end
459
-
460
480
  ensure
461
- if ws.config.import_log_enabled? && Autoproj::Ops::Snapshot.update_log_available?(manifest)
462
- update_log_for_processed_packages(all_processed_packages || Array.new, $!)
481
+ create_report(all_processed_packages || []) if @report_path
482
+
483
+ update_log = ws.config.import_log_enabled? &&
484
+ Autoproj::Ops::Snapshot.update_log_available?(manifest)
485
+ if update_log
486
+ update_log_for_processed_packages(
487
+ all_processed_packages || Array.new, $!)
463
488
  end
464
489
  end
465
490
 
491
+ # Call post-import blcoks registered for the given package
492
+ #
493
+ # @param [PackageDefinition] pkg
466
494
  def process_post_import_blocks(pkg)
467
495
  Autoproj.each_post_import_block(pkg) do |block|
468
496
  block.call(pkg)
469
497
  end
470
498
  end
471
499
 
500
+ def create_report(package_list)
501
+ FileUtils.mkdir_p File.dirname(@report_path)
502
+
503
+ packages = package_list.each_with_object({}) do |pkg_name, h|
504
+ pkg = @ws.manifest.find_autobuild_package(pkg_name)
505
+
506
+ h[pkg.name] = {
507
+ invoked: !!pkg.import_invoked?,
508
+ success: !!pkg.imported?
509
+ }
510
+ end
511
+
512
+ report = JSON.pretty_generate({
513
+ import_report: {
514
+ timestamp: Time.now,
515
+ packages: packages
516
+ }
517
+ })
518
+ IO.write(@report_path, report)
519
+ end
520
+
472
521
  def update_log_for_processed_packages(all_processed_packages, exception)
473
522
  all_updated_packages = all_processed_packages.find_all do |processed_pkg|
474
523
  processed_pkg.autobuild.updated?
475
524
  end
476
525
 
477
- if !all_updated_packages.empty?
526
+ unless all_updated_packages.empty?
478
527
  failure_message =
479
528
  if exception
480
529
  " (#{exception.message.split("\n").first})"
481
530
  end
482
531
  ops = Ops::Snapshot.new(ws.manifest, keep_going: true)
483
532
  ops.update_package_import_state(
484
- "#{$0} #{ARGV.join(" ")}#{failure_message}",
533
+ "#{$0} #{ARGV.join(' ')}#{failure_message}",
485
534
  all_updated_packages.map(&:name))
486
535
  end
487
536
  end
488
537
  end
489
538
  end
490
539
  end
491
-
492
-