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.
- checksums.yaml +4 -4
- data/.rubocop.yml +113 -0
- data/.travis.yml +0 -2
- data/Gemfile +1 -0
- data/README.md +59 -14
- data/bin/autoproj_bootstrap +21 -12
- data/bin/autoproj_bootstrap.in +2 -2
- data/bin/autoproj_install +21 -12
- data/bin/autoproj_install.in +2 -2
- data/lib/autoproj/aruba_minitest.rb +4 -4
- data/lib/autoproj/autobuild_extensions/dsl.rb +91 -70
- data/lib/autoproj/autobuild_extensions/package.rb +20 -1
- data/lib/autoproj/build_option.rb +24 -7
- data/lib/autoproj/cli/base.rb +12 -1
- data/lib/autoproj/cli/bootstrap.rb +9 -3
- data/lib/autoproj/cli/build.rb +17 -13
- data/lib/autoproj/cli/envsh.rb +1 -1
- data/lib/autoproj/cli/exec.rb +5 -7
- data/lib/autoproj/cli/main.rb +44 -9
- data/lib/autoproj/cli/main_test.rb +2 -0
- data/lib/autoproj/cli/test.rb +29 -6
- data/lib/autoproj/cli/version.rb +52 -0
- data/lib/autoproj/cli/versions.rb +4 -1
- data/lib/autoproj/cli/watch.rb +2 -1
- data/lib/autoproj/configuration.rb +49 -11
- data/lib/autoproj/default.osdeps +9 -0
- data/lib/autoproj/manifest.rb +6 -6
- data/lib/autoproj/ops/build.rb +5 -15
- data/lib/autoproj/ops/import.rb +22 -3
- data/lib/autoproj/ops/install.rb +19 -10
- data/lib/autoproj/ops/main_config_switcher.rb +12 -6
- data/lib/autoproj/ops/snapshot.rb +5 -1
- data/lib/autoproj/os_package_resolver.rb +245 -209
- data/lib/autoproj/package_selection.rb +18 -0
- data/lib/autoproj/reporter.rb +45 -31
- data/lib/autoproj/test.rb +107 -56
- data/lib/autoproj/version.rb +1 -1
- data/lib/autoproj/workspace.rb +90 -72
- data/shell/completion/amake_bash +1 -0
- data/shell/completion/amake_zsh +1 -0
- data/shell/completion/autoproj_bash +2 -0
- data/shell/completion/autoproj_zsh +2 -0
- metadata +5 -3
data/lib/autoproj/default.osdeps
CHANGED
@@ -162,6 +162,15 @@ pip:
|
|
162
162
|
freebsd: pip
|
163
163
|
default: ignore # assume pip will be installed by the user
|
164
164
|
|
165
|
+
python:
|
166
|
+
arch: python2
|
167
|
+
debian,ubuntu: python-dev
|
168
|
+
fedora: python-devel
|
169
|
+
freebsd: python-devel
|
170
|
+
gentoo: dev-lang/python
|
171
|
+
opensuse: python-devel
|
172
|
+
default: ignore # will be installed manually by the user
|
173
|
+
|
165
174
|
sudo:
|
166
175
|
macos-brew: ignore
|
167
176
|
default: sudo
|
data/lib/autoproj/manifest.rb
CHANGED
@@ -19,11 +19,11 @@ class Manifest
|
|
19
19
|
|
20
20
|
# Loads the manifest file located at +file+ and returns the Manifest
|
21
21
|
# instance that represents it
|
22
|
-
|
23
|
-
|
22
|
+
def self.load(file)
|
23
|
+
manifest = Manifest.new
|
24
24
|
manifest.load(file)
|
25
25
|
manifest
|
26
|
-
|
26
|
+
end
|
27
27
|
|
28
28
|
# A normalized version of the layout as represented in the manifest file
|
29
29
|
#
|
@@ -176,7 +176,7 @@ def initialize(ws, os_package_resolver: OSPackageResolver.new)
|
|
176
176
|
@ws = ws
|
177
177
|
@vcs = VCSDefinition.none
|
178
178
|
@file = nil
|
179
|
-
|
179
|
+
@data = Hash.new
|
180
180
|
@has_layout = false
|
181
181
|
@normalized_layout = Hash.new
|
182
182
|
@packages = Hash.new
|
@@ -198,7 +198,7 @@ def initialize(ws, os_package_resolver: OSPackageResolver.new)
|
|
198
198
|
|
199
199
|
@constant_definitions = Hash.new
|
200
200
|
@package_sets << LocalPackageSet.new(ws)
|
201
|
-
|
201
|
+
end
|
202
202
|
|
203
203
|
# @api private
|
204
204
|
#
|
@@ -994,7 +994,7 @@ def load_package_manifest(pkg)
|
|
994
994
|
|
995
995
|
# Look for the package's manifest.xml, but fallback to a manifest in
|
996
996
|
# the package set if present
|
997
|
-
if package.use_package_xml?
|
997
|
+
if package.use_package_xml? && package.checked_out?
|
998
998
|
manifest_path = File.join(package.srcdir, "package.xml")
|
999
999
|
raise NoPackageXML.new(package.srcdir), "#{package.name} from "\
|
1000
1000
|
"#{package_set.name} has use_package_xml set, but the package has "\
|
data/lib/autoproj/ops/build.rb
CHANGED
@@ -13,9 +13,9 @@ class Build
|
|
13
13
|
|
14
14
|
# @param [String] report_dir the log directory in which to build
|
15
15
|
# the build report. If left to nil, no report will be generated
|
16
|
-
def initialize(manifest,
|
16
|
+
def initialize(manifest, report_path: nil)
|
17
17
|
@manifest = manifest
|
18
|
-
@
|
18
|
+
@report_path = report_path
|
19
19
|
end
|
20
20
|
|
21
21
|
# Triggers a rebuild of all packages
|
@@ -92,22 +92,12 @@ 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 @
|
95
|
+
build_report(all_enabled_packages) if @report_path
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
-
REPORT_BASENAME = "build_report.json"
|
100
|
-
|
101
|
-
# The path to the report file
|
102
|
-
#
|
103
|
-
# @return [String,nil] the path, or nil if the report should not
|
104
|
-
# be generated
|
105
|
-
def report_path
|
106
|
-
File.join(@report_dir, REPORT_BASENAME) if @report_dir
|
107
|
-
end
|
108
|
-
|
109
99
|
def build_report(package_list)
|
110
|
-
FileUtils.mkdir_p @
|
100
|
+
FileUtils.mkdir_p File.dirname(@report_path)
|
111
101
|
|
112
102
|
packages = package_list.map do |pkg_name|
|
113
103
|
pkg = manifest.find_autobuild_package(pkg_name)
|
@@ -130,7 +120,7 @@ def build_report(package_list)
|
|
130
120
|
packages: packages
|
131
121
|
}
|
132
122
|
})
|
133
|
-
IO.write(report_path, build_report)
|
123
|
+
IO.write(@report_path, build_report)
|
134
124
|
end
|
135
125
|
end
|
136
126
|
end
|
data/lib/autoproj/ops/import.rb
CHANGED
@@ -73,7 +73,7 @@ def import_next_step(pkg, reverse_dependencies)
|
|
73
73
|
end
|
74
74
|
new_packages
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
def pre_package_import(selection, manifest, pkg, reverse_dependencies)
|
78
78
|
# Try to auto-exclude the package early. If the autobuild file
|
79
79
|
# contained some information that allows us to exclude it now,
|
@@ -133,12 +133,30 @@ def install_vcs_packages_for(*packages, **osdeps_options)
|
|
133
133
|
vcs_to_install
|
134
134
|
end
|
135
135
|
|
136
|
+
# Install the internal dependencies for the given packages
|
137
|
+
#
|
138
|
+
# @param [Hash] osdeps_options the options that will be passed to
|
139
|
+
# {Workspace#install_os_packages}
|
140
|
+
# @return [Set] the set of installed OS packages
|
141
|
+
def install_internal_dependencies_for(*packages, **osdeps_options)
|
142
|
+
packages_to_install = packages.map do |pkg|
|
143
|
+
pkg.autobuild.internal_dependencies
|
144
|
+
end.flatten.uniq
|
145
|
+
return if packages_to_install.empty?
|
146
|
+
|
147
|
+
# This assumes that the internal dependencies do not depend on a
|
148
|
+
# 'strict' package mangers such as e.g. BundlerManager and that
|
149
|
+
# the package manager itself does not have any dependencies
|
150
|
+
ws.install_os_packages(packages_to_install, all: nil, **osdeps_options)
|
151
|
+
packages_to_install
|
152
|
+
end
|
153
|
+
|
136
154
|
# @api private
|
137
155
|
#
|
138
156
|
# Queue the work necessary to import the given package, making sure
|
139
157
|
# that the execution results end up in a given queue
|
140
158
|
#
|
141
|
-
# @param executor the future executor
|
159
|
+
# @param executor the future executor
|
142
160
|
# @param [Queue] completion_queue the queue where the completion
|
143
161
|
# results should be pushed, as a (package, time, result,
|
144
162
|
# error_reason) tuple
|
@@ -331,7 +349,7 @@ def import_selected_packages(selection,
|
|
331
349
|
executor.wait_for_termination
|
332
350
|
end
|
333
351
|
end
|
334
|
-
|
352
|
+
|
335
353
|
def finalize_package_load(processed_packages, auto_exclude: auto_exclude?)
|
336
354
|
manifest = ws.manifest
|
337
355
|
|
@@ -405,6 +423,7 @@ def import_packages(selection,
|
|
405
423
|
raise failures.first
|
406
424
|
end
|
407
425
|
|
426
|
+
install_internal_dependencies_for(*all_processed_packages)
|
408
427
|
finalize_package_load(all_processed_packages, auto_exclude: auto_exclude)
|
409
428
|
|
410
429
|
all_enabled_osdeps = selection.each_osdep_package_name.to_set
|
data/lib/autoproj/ops/install.rb
CHANGED
@@ -229,6 +229,9 @@ def parse_options(args = ARGV)
|
|
229
229
|
opt.on '--skip-stage2', 'do not run the stage2 install' do
|
230
230
|
@skip_stage2 = true
|
231
231
|
end
|
232
|
+
opt.on '--debug', 'Run in debug mode' do
|
233
|
+
@autoproj_options << '--debug'
|
234
|
+
end
|
232
235
|
opt.on '--gem-source=URL', String, "use this source for RubyGems "\
|
233
236
|
"instead of rubygems.org" do |url|
|
234
237
|
@gem_source = url
|
@@ -265,19 +268,25 @@ def parse_options(args = ARGV)
|
|
265
268
|
end
|
266
269
|
opt.on '--[no-]color', 'do not use colored output (enabled by "\
|
267
270
|
"default if the terminal supports it)' do |color|
|
268
|
-
if color then autoproj_options << "--color"
|
269
|
-
else autoproj_options << '--no-color'
|
271
|
+
if color then @autoproj_options << "--color"
|
272
|
+
else @autoproj_options << '--no-color'
|
270
273
|
end
|
271
274
|
end
|
272
275
|
opt.on '--[no-]progress', 'do not use progress output (enabled by "\
|
273
|
-
"default if the terminal supports it)' do |
|
274
|
-
if
|
275
|
-
else autoproj_options << '--no-progress'
|
276
|
+
"default if the terminal supports it)' do |progress|
|
277
|
+
if progress then @autoproj_options << "--progress"
|
278
|
+
else @autoproj_options << '--no-progress'
|
279
|
+
end
|
280
|
+
end
|
281
|
+
opt.on '--[no-]interactive', 'if non-interactive, use default "\
|
282
|
+
"answer for questions' do |flag|
|
283
|
+
if flag then @autoproj_options << "--interactive"
|
284
|
+
else @autoproj_options << "--no-interactive"
|
276
285
|
end
|
277
286
|
end
|
278
287
|
end
|
279
288
|
args = options.parse(ARGV)
|
280
|
-
autoproj_options + args
|
289
|
+
@autoproj_options + args
|
281
290
|
end
|
282
291
|
|
283
292
|
def find_bundler(gem_program)
|
@@ -667,7 +676,7 @@ def autoproj_path
|
|
667
676
|
|
668
677
|
def run_autoproj(*args)
|
669
678
|
system env_for_child.merge('BUNDLE_GEMFILE' => autoproj_gemfile_path),
|
670
|
-
Gem.ruby, autoproj_path, *args,
|
679
|
+
Gem.ruby, autoproj_path, *args, *@autoproj_options
|
671
680
|
end
|
672
681
|
|
673
682
|
def v1_workspace?
|
@@ -691,7 +700,7 @@ def call_stage2
|
|
691
700
|
clean_env = env_for_child
|
692
701
|
stage2_vars = clean_env.map { |k, v| "#{k}=#{v}" }
|
693
702
|
puts "starting the newly installed autoproj for stage2 install"
|
694
|
-
if !run_autoproj('install-stage2', root_dir, *stage2_vars)
|
703
|
+
if !run_autoproj('install-stage2', root_dir, *stage2_vars, *@autoproj_options)
|
695
704
|
raise "failed to execute autoproj install-stage2"
|
696
705
|
end
|
697
706
|
end
|
@@ -701,7 +710,7 @@ def stage2(*vars)
|
|
701
710
|
puts "saving temporary env.sh and .autoproj/env.sh"
|
702
711
|
save_env_sh(*vars)
|
703
712
|
puts "running 'autoproj envsh' to generate a proper env.sh"
|
704
|
-
if !system(Gem.ruby, autoproj_path, 'envsh',
|
713
|
+
if !system(Gem.ruby, autoproj_path, 'envsh', *@autoproj_options)
|
705
714
|
STDERR.puts "failed to run autoproj envsh on the newly installed "\
|
706
715
|
"autoproj (#{autoproj_path})"
|
707
716
|
exit 1
|
@@ -709,7 +718,7 @@ def stage2(*vars)
|
|
709
718
|
# This is really needed on an existing install to install the
|
710
719
|
# gems that were present in the v1 layout
|
711
720
|
puts "running 'autoproj osdeps' to re-install missing gems"
|
712
|
-
if !system(Gem.ruby, autoproj_path, 'osdeps')
|
721
|
+
if !system(Gem.ruby, autoproj_path, 'osdeps', *@autoproj_options)
|
713
722
|
STDERR.puts "failed to run autoproj osdeps on the newly installed "\
|
714
723
|
"autoproj (#{autoproj_path})"
|
715
724
|
exit 1
|
@@ -16,16 +16,20 @@ def initialize(ws)
|
|
16
16
|
EXPECTED_ROOT_ENTRIES = [".", "..", "autoproj_bootstrap",
|
17
17
|
".autoproj", "bootstrap.sh", ENV_FILENAME].to_set
|
18
18
|
|
19
|
+
|
20
|
+
def check_root_dir_empty?
|
21
|
+
(ENV['AUTOPROJ_NONINTERACTIVE'] != '1') &&
|
22
|
+
(ENV['AUTOPROJ_BOOTSTRAP_IGNORE_NONEMPTY_DIR'] != '1')
|
23
|
+
end
|
24
|
+
|
19
25
|
# Verifies that {#root_dir} contains only expected entries, to make
|
20
26
|
# sure that the user bootstraps into a new directory
|
21
27
|
#
|
22
28
|
# If the environment variable AUTOPROJ_BOOTSTRAP_IGNORE_NONEMPTY_DIR
|
23
29
|
# is set to 1, the check is skipped
|
24
30
|
def check_root_dir_empty
|
25
|
-
return if ENV['AUTOPROJ_BOOTSTRAP_IGNORE_NONEMPTY_DIR'] == '1'
|
26
|
-
|
27
31
|
require 'set'
|
28
|
-
curdir_entries = Dir.entries(ws.root_dir).map { |p| File.basename(p) }.to_set -
|
32
|
+
curdir_entries = Dir.entries(ws.root_dir).map { |p| File.basename(p) }.to_set -
|
29
33
|
EXPECTED_ROOT_ENTRIES
|
30
34
|
return if curdir_entries.empty?
|
31
35
|
|
@@ -73,8 +77,10 @@ def validate_autoproj_current_root(reuse)
|
|
73
77
|
|
74
78
|
MAIN_CONFIGURATION_TEMPLATE = File.expand_path(File.join("..", "..", "..", "samples", 'autoproj'), File.dirname(__FILE__))
|
75
79
|
|
76
|
-
def bootstrap(buildconf_info,
|
77
|
-
|
80
|
+
def bootstrap(buildconf_info,
|
81
|
+
check_root_dir_empty: check_root_dir_empty?,
|
82
|
+
reuse: Array.new)
|
83
|
+
self.check_root_dir_empty if check_root_dir_empty
|
78
84
|
validate_autoproj_current_root(reuse)
|
79
85
|
|
80
86
|
ws.config.validate_ruby_executable
|
@@ -179,7 +185,7 @@ def do_switch_config(delete_current, type, url, *options)
|
|
179
185
|
backup_name = "#{backup_base_name}-#{index}.bak"
|
180
186
|
index += 1
|
181
187
|
end
|
182
|
-
|
188
|
+
|
183
189
|
FileUtils.mv config_dir, backup_name
|
184
190
|
end
|
185
191
|
|
@@ -117,7 +117,7 @@ def error_or_warn(package, error)
|
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
|
-
def snapshot_packages(packages, target_dir = nil, only_local: true)
|
120
|
+
def snapshot_packages(packages, target_dir = nil, only_local: true, fingerprint: false)
|
121
121
|
result = Array.new
|
122
122
|
packages.each do |package_name|
|
123
123
|
package = manifest.find_package_definition(package_name)
|
@@ -140,6 +140,10 @@ def snapshot_packages(packages, target_dir = nil, only_local: true)
|
|
140
140
|
next
|
141
141
|
end
|
142
142
|
|
143
|
+
if fingerprint
|
144
|
+
vcs_info['fingerprint'] = package.autobuild.fingerprint
|
145
|
+
end
|
146
|
+
|
143
147
|
if vcs_info
|
144
148
|
result << Hash[package_name, vcs_info]
|
145
149
|
else
|
@@ -5,31 +5,35 @@ module Autoproj
|
|
5
5
|
# Manager for packages provided by external package managers
|
6
6
|
class OSPackageResolver
|
7
7
|
def self.load(file, suffixes: [], **options)
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
unless File.file?(file)
|
9
|
+
raise ArgumentError, "no such file or directory #{file}"
|
10
|
+
end
|
11
|
+
|
12
|
+
candidates = [file]
|
13
|
+
candidates.concat(suffixes.map { |s| "#{file}-#{s}" })
|
11
14
|
|
12
|
-
|
13
|
-
|
15
|
+
error_t =
|
16
|
+
if defined? Psych::SyntaxError
|
17
|
+
[ArgumentError, Psych::SyntaxError]
|
18
|
+
else ArgumentError
|
19
|
+
end
|
14
20
|
|
15
|
-
|
16
|
-
|
17
|
-
|
21
|
+
result = new(**options)
|
22
|
+
candidates.each do |file_candidate|
|
23
|
+
next unless File.file?(file_candidate)
|
18
24
|
|
19
|
-
result = new(**options)
|
20
|
-
candidates.each do |file_candidate|
|
21
|
-
next if !File.file?(file_candidate)
|
22
25
|
file_candidate = File.expand_path(file_candidate)
|
23
26
|
begin
|
24
|
-
data = YAML.
|
27
|
+
data = YAML.safe_load(File.read(file_candidate)) || Hash.new
|
25
28
|
verify_definitions(data)
|
26
29
|
rescue *error_t => e
|
27
|
-
raise ConfigError.new, "error in #{file_candidate}:
|
30
|
+
raise ConfigError.new, "error in #{file_candidate}: "\
|
31
|
+
"#{e.message}", e.backtrace
|
28
32
|
end
|
29
33
|
|
30
34
|
result.merge(new(data, file_candidate, **options))
|
31
|
-
|
32
|
-
|
35
|
+
end
|
36
|
+
result
|
33
37
|
end
|
34
38
|
|
35
39
|
# The underlying workspace
|
@@ -43,11 +47,12 @@ def self.autodetect_ruby_program
|
|
43
47
|
ruby_executable
|
44
48
|
end
|
45
49
|
|
46
|
-
AUTOPROJ_OSDEPS = File.join(
|
50
|
+
AUTOPROJ_OSDEPS = File.join(__dir__, 'default.osdeps')
|
47
51
|
def self.load_default
|
48
52
|
file = ENV['AUTOPROJ_DEFAULT_OSDEPS'] || AUTOPROJ_OSDEPS
|
49
|
-
|
50
|
-
Autoproj.warn "#{file} (from AUTOPROJ_DEFAULT_OSDEPS) is not a file,
|
53
|
+
unless File.file?(file)
|
54
|
+
Autoproj.warn "#{file} (from AUTOPROJ_DEFAULT_OSDEPS) is not a file, "\
|
55
|
+
"falling back to #{AUTOPROJ_OSDEPS}"
|
51
56
|
file = AUTOPROJ_OSDEPS
|
52
57
|
end
|
53
58
|
load(file)
|
@@ -58,7 +63,7 @@ def load_default
|
|
58
63
|
end
|
59
64
|
|
60
65
|
PACKAGE_MANAGERS = OSPackageInstaller::PACKAGE_MANAGERS.keys
|
61
|
-
|
66
|
+
|
62
67
|
# Mapping from OS name to package manager name
|
63
68
|
#
|
64
69
|
# Package handlers and OSes MUST have different names. The former are
|
@@ -71,15 +76,15 @@ def load_default
|
|
71
76
|
#
|
72
77
|
# we need to be able to separate between OS and package manager names.
|
73
78
|
OS_PACKAGE_MANAGERS = {
|
74
|
-
'debian'
|
75
|
-
'gentoo'
|
76
|
-
'arch'
|
77
|
-
'fedora'
|
79
|
+
'debian' => 'apt-dpkg',
|
80
|
+
'gentoo' => 'emerge',
|
81
|
+
'arch' => 'pacman',
|
82
|
+
'fedora' => 'yum',
|
78
83
|
'macos-port' => 'macports',
|
79
84
|
'macos-brew' => 'brew',
|
80
|
-
'opensuse'
|
81
|
-
'freebsd'
|
82
|
-
}
|
85
|
+
'opensuse' => 'zypper',
|
86
|
+
'freebsd' => 'pkg'
|
87
|
+
}.freeze
|
83
88
|
|
84
89
|
# The information contained in the OSdeps files, as a hash
|
85
90
|
attr_reader :definitions
|
@@ -93,16 +98,20 @@ def load_default
|
|
93
98
|
# Controls whether the package resolver will prefer installing
|
94
99
|
# OS-independent packages (such as e.g. Gems) over their OS-provided
|
95
100
|
# equivalent (e.g. the packaged version of a gem)
|
96
|
-
def prefer_indep_over_os_packages
|
101
|
+
def prefer_indep_over_os_packages?
|
102
|
+
@prefer_indep_over_os_packages
|
103
|
+
end
|
97
104
|
# (see prefer_indep_over_os_packages?)
|
98
|
-
|
105
|
+
attr_writer :prefer_indep_over_os_packages
|
99
106
|
# Cached results of {#resolve_package}
|
100
107
|
attr_reader :resolve_package_cache
|
101
108
|
|
102
109
|
# Use to override the autodetected OS-specific package handler
|
103
110
|
def os_package_manager=(manager_name)
|
104
111
|
if manager_name && !package_managers.include?(manager_name)
|
105
|
-
raise ArgumentError, "#{manager_name} is not a known
|
112
|
+
raise ArgumentError, "#{manager_name} is not a known "\
|
113
|
+
"package manager, known managers are "\
|
114
|
+
"#{package_managers.to_a.sort.join(', ')}"
|
106
115
|
end
|
107
116
|
@os_package_manager = manager_name
|
108
117
|
end
|
@@ -111,13 +120,12 @@ def os_package_manager=(manager_name)
|
|
111
120
|
#
|
112
121
|
# @return [String]
|
113
122
|
def os_package_manager
|
114
|
-
|
115
|
-
os_names,
|
123
|
+
unless @os_package_manager
|
124
|
+
os_names, = operating_system
|
116
125
|
os_name = os_names.find { |name| OS_PACKAGE_MANAGERS[name] }
|
117
|
-
@os_package_manager = OS_PACKAGE_MANAGERS[os_name] ||
|
118
|
-
'unknown'
|
126
|
+
@os_package_manager = OS_PACKAGE_MANAGERS[os_name] || 'unknown'
|
119
127
|
end
|
120
|
-
|
128
|
+
@os_package_manager
|
121
129
|
end
|
122
130
|
|
123
131
|
# Returns the set of known package managers
|
@@ -143,7 +151,7 @@ def initialize(defs = Hash.new, file = nil,
|
|
143
151
|
@prefer_indep_over_os_packages = false
|
144
152
|
@aliases = Hash.new
|
145
153
|
|
146
|
-
@sources
|
154
|
+
@sources = Hash.new
|
147
155
|
@installed_packages = Set.new
|
148
156
|
@operating_system = operating_system
|
149
157
|
@supported_operating_system = nil
|
@@ -195,57 +203,58 @@ def invalidate_resolve_package_cache
|
|
195
203
|
# takes precedence
|
196
204
|
def merge(info, suffixes: [])
|
197
205
|
@definitions = definitions.merge(info.definitions) do |h, v1, v2|
|
198
|
-
if v1 != v2
|
199
|
-
warn_about_merge_collisions(info, suffixes, h, v1, v2)
|
200
|
-
end
|
206
|
+
warn_about_merge_collisions(info, suffixes, h, v1, v2) if v1 != v2
|
201
207
|
v2
|
202
208
|
end
|
203
209
|
invalidate_resolve_package_cache
|
204
210
|
|
205
211
|
@sources = sources.merge(info.sources)
|
206
|
-
@all_definitions = all_definitions.
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
entry
|
212
|
+
@all_definitions = all_definitions.
|
213
|
+
merge(info.all_definitions) do |_package_name, all_defs, new_all_defs|
|
214
|
+
all_defs = all_defs.dup
|
215
|
+
new_all_defs = new_all_defs.dup
|
216
|
+
new_all_defs.delete_if do |files, data|
|
217
|
+
if (entry = all_defs.find { |_, d| d == data })
|
218
|
+
entry[0] |= files
|
219
|
+
end
|
212
220
|
end
|
221
|
+
all_defs.concat(new_all_defs)
|
213
222
|
end
|
214
|
-
all_defs.concat(new_all_defs)
|
215
|
-
end
|
216
223
|
end
|
217
224
|
|
218
225
|
# @api private
|
219
226
|
#
|
220
227
|
# Warn about a collision (override) detected during #merge
|
221
|
-
def warn_about_merge_collisions(merged_info, suffixes, key,
|
228
|
+
def warn_about_merge_collisions(merged_info, suffixes, key,
|
229
|
+
_old_value, _new_value)
|
222
230
|
old = source_of(key)
|
223
231
|
new = merged_info.source_of(key)
|
224
232
|
|
225
|
-
if suffixes.any? { |s| "#{old}#{s}"
|
226
|
-
return
|
227
|
-
end
|
233
|
+
return if suffixes.any? { |s| new == "#{old}#{s}" }
|
228
234
|
|
229
235
|
# Warn if the new osdep definition resolves to a different
|
230
236
|
# set of packages than the old one
|
231
|
-
old_resolved = resolve_package(key, resolve_recursive: false).
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
new_resolved = merged_info.resolve_package(key, resolve_recursive: false).
|
236
|
-
|
237
|
-
|
238
|
-
|
237
|
+
old_resolved = resolve_package(key, resolve_recursive: false).
|
238
|
+
each_with_object(Hash.new) do |(handler, status, list), osdep_h|
|
239
|
+
osdep_h[handler] = [status, list.dup]
|
240
|
+
end
|
241
|
+
new_resolved = merged_info.resolve_package(key, resolve_recursive: false).
|
242
|
+
each_with_object(Hash.new) do |(handler, status, list), osdep_h|
|
243
|
+
osdep_h[handler] = [status, list.dup]
|
244
|
+
end
|
239
245
|
if old_resolved != new_resolved
|
240
|
-
Autoproj.warn "osdeps definition for #{key},
|
246
|
+
Autoproj.warn "osdeps definition for #{key}, "\
|
247
|
+
"previously defined in #{old} overridden by #{new}:"
|
241
248
|
first = true
|
242
249
|
old_resolved.each do |handler, (_, packages)|
|
243
|
-
Autoproj.warn " #{first ? 'resp. ' : ' '}#{handler}:
|
250
|
+
Autoproj.warn " #{first ? 'resp. ' : ' '}#{handler}: "\
|
251
|
+
"#{packages.map(&:to_s).join(', ')}"
|
244
252
|
first = false
|
245
253
|
end
|
246
254
|
first = true
|
247
255
|
new_resolved.each do |handler, (_, packages)|
|
248
|
-
Autoproj.warn " #{first ? 'and ' : ' '}#{handler}:
|
256
|
+
Autoproj.warn " #{first ? 'and ' : ' '}#{handler}: "\
|
257
|
+
"#{packages.map(&:to_s).join(', ')}"
|
249
258
|
first = false
|
250
259
|
end
|
251
260
|
end
|
@@ -255,25 +264,27 @@ def warn_about_merge_collisions(merged_info, suffixes, key, old_value, new_value
|
|
255
264
|
def self.verify_definitions(hash, path = [])
|
256
265
|
hash.each do |key, value|
|
257
266
|
if value && !key.kind_of?(String)
|
258
|
-
raise ArgumentError, "invalid osdeps definition:
|
267
|
+
raise ArgumentError, "invalid osdeps definition: "\
|
268
|
+
"found an #{key.class} as a key in #{path.join('/')}. "\
|
269
|
+
"Don't forget to put quotes around numbers"
|
259
270
|
elsif !value && (key.kind_of?(Hash) || key.kind_of?(Array))
|
260
271
|
verify_definitions(key)
|
261
272
|
end
|
262
|
-
next
|
273
|
+
next unless value
|
263
274
|
|
264
275
|
if value.kind_of?(Array) || value.kind_of?(Hash)
|
265
276
|
verify_definitions(value, (path + [key]))
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
277
|
+
elsif !value.kind_of?(String)
|
278
|
+
raise ArgumentError, "invalid osdeps definition: "\
|
279
|
+
"found an #{value.class} as a value in #{path.join('/')}. "\
|
280
|
+
"Don't forget to put quotes around numbers"
|
270
281
|
end
|
271
282
|
end
|
272
283
|
end
|
273
284
|
|
274
285
|
# Whether the operating system could be autodetected successfully
|
275
286
|
def known_operating_system?
|
276
|
-
os_names,
|
287
|
+
os_names, = operating_system
|
277
288
|
!os_names.empty?
|
278
289
|
end
|
279
290
|
|
@@ -283,24 +294,20 @@ def supported_operating_system?
|
|
283
294
|
if @supported_operating_system.nil?
|
284
295
|
@supported_operating_system = (os_package_manager != 'unknown')
|
285
296
|
end
|
286
|
-
|
297
|
+
@supported_operating_system
|
287
298
|
end
|
288
299
|
|
289
300
|
def self.guess_operating_system
|
290
301
|
if File.exist?('/etc/debian_version')
|
291
302
|
versions = [File.read('/etc/debian_version').strip]
|
292
|
-
if versions.first =~ /sid/
|
293
|
-
versions = ["unstable", "sid"]
|
294
|
-
end
|
303
|
+
versions = %w[unstable sid] if versions.first =~ /sid/
|
295
304
|
[['debian'], versions]
|
296
305
|
elsif File.exist?('/etc/redhat-release')
|
297
306
|
release_string = File.read('/etc/redhat-release').strip
|
298
307
|
release_string =~ /(.*) release ([\d.]+)/
|
299
308
|
name = $1.downcase
|
300
309
|
version = $2
|
301
|
-
if name =~ /Red Hat Entreprise/
|
302
|
-
name = 'rhel'
|
303
|
-
end
|
310
|
+
name = 'rhel' if name =~ /Red Hat Entreprise/
|
304
311
|
[[name], [version]]
|
305
312
|
elsif File.exist?('/etc/gentoo-release')
|
306
313
|
release_string = File.read('/etc/gentoo-release').strip
|
@@ -309,19 +316,19 @@ def self.guess_operating_system
|
|
309
316
|
[['gentoo'], [version]]
|
310
317
|
elsif File.exist?('/etc/arch-release')
|
311
318
|
[['arch'], []]
|
312
|
-
elsif Autobuild.macos?
|
313
|
-
version
|
319
|
+
elsif Autobuild.macos?
|
320
|
+
version = `sw_vers | head -2 | tail -1`.split(":")[1]
|
314
321
|
manager =
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
end
|
319
|
-
if !OS_PACKAGE_MANAGERS.has_key?(manager)
|
322
|
+
ENV['AUTOPROJ_MACOSX_PACKAGE_MANAGER'] ||
|
323
|
+
'macos-brew'
|
324
|
+
unless OS_PACKAGE_MANAGERS.key?(manager)
|
320
325
|
known_managers = OS_PACKAGE_MANAGERS.keys.grep(/^macos/)
|
321
|
-
raise ArgumentError, "#{manager} is not a known MacOSX
|
326
|
+
raise ArgumentError, "#{manager} is not a known MacOSX "\
|
327
|
+
"package manager. Known package managers are "\
|
328
|
+
"#{known_managers.join(', ')}"
|
322
329
|
end
|
323
330
|
|
324
|
-
managers =
|
331
|
+
managers =
|
325
332
|
if manager == 'macos-port'
|
326
333
|
[manager, 'port']
|
327
334
|
else [manager]
|
@@ -331,12 +338,12 @@ def self.guess_operating_system
|
|
331
338
|
[['windows'], []]
|
332
339
|
elsif File.exist?('/etc/SuSE-release')
|
333
340
|
version = File.read('/etc/SuSE-release').strip
|
334
|
-
version
|
341
|
+
version =~ /.*VERSION\s+=\s+([^\s]+)/
|
335
342
|
version = $1
|
336
343
|
[['opensuse'], [version.strip]]
|
337
|
-
elsif Autobuild.freebsd?
|
338
|
-
|
339
|
-
|
344
|
+
elsif Autobuild.freebsd?
|
345
|
+
version = `uname -r`.strip.split("-")[0]
|
346
|
+
[['freebsd'], [version]]
|
340
347
|
end
|
341
348
|
end
|
342
349
|
|
@@ -349,21 +356,17 @@ def self.ensure_derivatives_refer_to_their_parents(names)
|
|
349
356
|
'/etc/arch-release' => 'arch',
|
350
357
|
'/etc/SuSE-release' => 'opensuse']
|
351
358
|
version_files.each do |file, name|
|
352
|
-
if File.exist?(file) && !names.include?(name)
|
353
|
-
names << name
|
354
|
-
end
|
359
|
+
names << name if File.exist?(file) && !names.include?(name)
|
355
360
|
end
|
356
361
|
names
|
357
362
|
end
|
358
|
-
|
363
|
+
|
359
364
|
def self.normalize_os_representation(names, versions)
|
360
365
|
# Normalize the names to lowercase
|
361
366
|
names = names.map(&:downcase)
|
362
367
|
versions = versions.map(&:downcase)
|
363
|
-
|
364
|
-
|
365
|
-
end
|
366
|
-
return names, versions
|
368
|
+
versions += ['default'] unless versions.include?('default')
|
369
|
+
[names, versions]
|
367
370
|
end
|
368
371
|
|
369
372
|
# The operating system self is targetting
|
@@ -392,20 +395,18 @@ def operating_system=(values)
|
|
392
395
|
#
|
393
396
|
# Examples: ['debian', ['sid', 'unstable']] or ['ubuntu', ['lucid lynx', '10.04']]
|
394
397
|
def self.autodetect_operating_system
|
395
|
-
if user_os = ENV['AUTOPROJ_OS']
|
398
|
+
if (user_os = ENV['AUTOPROJ_OS'])
|
396
399
|
if user_os.empty?
|
397
400
|
return false
|
398
401
|
else
|
399
402
|
names, versions = user_os.split(':')
|
400
|
-
return normalize_os_representation(
|
403
|
+
return normalize_os_representation(
|
404
|
+
names.split(','), versions.split(','))
|
401
405
|
end
|
402
406
|
end
|
403
407
|
|
404
408
|
names, versions = os_from_os_release
|
405
|
-
|
406
|
-
if !names
|
407
|
-
names, versions = guess_operating_system
|
408
|
-
end
|
409
|
+
names, versions = guess_operating_system unless names
|
409
410
|
|
410
411
|
# on Debian, they refuse to put enough information to detect
|
411
412
|
# 'unstable' reliably. So, we use the heuristic method for it
|
@@ -416,21 +417,19 @@ def self.autodetect_operating_system
|
|
416
417
|
# phase...
|
417
418
|
if File.exist?('/etc/debian_version')
|
418
419
|
debian_versions = [File.read('/etc/debian_version').strip]
|
419
|
-
if debian_versions.first =~ /sid/
|
420
|
-
versions = ["unstable", "sid"]
|
421
|
-
end
|
420
|
+
versions = %w[unstable sid] if debian_versions.first =~ /sid/
|
422
421
|
end
|
423
422
|
# otherwise "versions" contains the result it previously had
|
424
423
|
end
|
425
|
-
return
|
424
|
+
return unless names
|
426
425
|
|
427
426
|
names = ensure_derivatives_refer_to_their_parents(names)
|
428
427
|
names, versions = normalize_os_representation(names, versions)
|
429
|
-
|
428
|
+
[names, versions]
|
430
429
|
end
|
431
430
|
|
432
431
|
def self.os_from_os_release(filename = '/etc/os-release')
|
433
|
-
return
|
432
|
+
return unless File.exist?(filename)
|
434
433
|
|
435
434
|
fields = Hash.new
|
436
435
|
File.readlines(filename).each do |line|
|
@@ -438,7 +437,8 @@ def self.os_from_os_release(filename = '/etc/os-release')
|
|
438
437
|
if line.strip =~ /^(\w+)=(?:["'])?([^"']+)(?:["'])?$/
|
439
438
|
fields[$1] = $2
|
440
439
|
elsif !line.empty?
|
441
|
-
Autoproj.warn "could not parse line '#{line.inspect}'
|
440
|
+
Autoproj.warn "could not parse line '#{line.inspect}' "\
|
441
|
+
"in /etc/os-release"
|
442
442
|
end
|
443
443
|
end
|
444
444
|
|
@@ -448,19 +448,17 @@ def self.os_from_os_release(filename = '/etc/os-release')
|
|
448
448
|
versions << fields['VERSION_ID']
|
449
449
|
version = fields['VERSION'] || ''
|
450
450
|
versions.concat(version.gsub(/[^\w.]/, ' ').split(' '))
|
451
|
-
|
451
|
+
[names.compact.uniq, versions.compact.uniq]
|
452
452
|
end
|
453
453
|
|
454
454
|
def self.os_from_lsb
|
455
|
-
|
456
|
-
return
|
457
|
-
end
|
455
|
+
return unless Autobuild.find_in_path('lsb_release')
|
458
456
|
|
459
457
|
distributor = [`lsb_release -i -s`.strip.downcase]
|
460
458
|
codename = `lsb_release -c -s`.strip.downcase
|
461
459
|
version = `lsb_release -r -s`.strip.downcase
|
462
460
|
|
463
|
-
|
461
|
+
[distributor, [codename, version]]
|
464
462
|
end
|
465
463
|
|
466
464
|
class InvalidRecursiveStatement < Autobuild::Exception; end
|
@@ -471,8 +469,8 @@ class InvalidRecursiveStatement < Autobuild::Exception; end
|
|
471
469
|
# returns an array contain the path starting with name and
|
472
470
|
# ending at the resolved name
|
473
471
|
def resolve_name(name)
|
474
|
-
path = [
|
475
|
-
while aliases.
|
472
|
+
path = [name]
|
473
|
+
while aliases.key?(name)
|
476
474
|
name = aliases[name]
|
477
475
|
path << name
|
478
476
|
end
|
@@ -482,7 +480,9 @@ def resolve_name(name)
|
|
482
480
|
# Null object class that is used to mark recursive resolution when
|
483
481
|
# calling {#resolve_package} with resolve_recursive set to false
|
484
482
|
class OSDepRecursiveResolver
|
485
|
-
def self.to_s
|
483
|
+
def self.to_s
|
484
|
+
'osdep'.freeze
|
485
|
+
end
|
486
486
|
end
|
487
487
|
|
488
488
|
# Return the list of packages that should be installed for +name+
|
@@ -503,17 +503,13 @@ def self.to_s; 'osdep' end
|
|
503
503
|
# name and version. The package list might be empty even if status ==
|
504
504
|
# FOUND_PACKAGES, for instance if the ignore keyword is used.
|
505
505
|
def resolve_package(name, resolve_recursive: true)
|
506
|
-
if resolve_package_cache.
|
507
|
-
return resolve_package_cache[name]
|
508
|
-
end
|
506
|
+
return resolve_package_cache[name] if resolve_package_cache.key?(name)
|
509
507
|
|
510
508
|
path = resolve_name(name)
|
511
509
|
name = path.last
|
512
510
|
|
513
511
|
dep_def = definitions[name]
|
514
|
-
|
515
|
-
return (resolve_package_cache[name] = nil)
|
516
|
-
end
|
512
|
+
return (resolve_package_cache[name] = nil) unless dep_def
|
517
513
|
|
518
514
|
os_names, os_versions = operating_system
|
519
515
|
|
@@ -534,27 +530,28 @@ def resolve_package(name, resolve_recursive: true)
|
|
534
530
|
end
|
535
531
|
|
536
532
|
result = []
|
537
|
-
found, pkg = partition_osdep_entry(
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
end
|
533
|
+
found, pkg = partition_osdep_entry(
|
534
|
+
name, dep_def, nil,
|
535
|
+
(package_managers - [os_package_manager]), os_names, os_versions)
|
536
|
+
result << [os_package_manager, found, pkg] if found
|
542
537
|
|
543
538
|
package_managers.each do |handler|
|
544
|
-
found, pkg = partition_osdep_entry(
|
545
|
-
|
546
|
-
|
547
|
-
end
|
539
|
+
found, pkg = partition_osdep_entry(
|
540
|
+
name, dep_def, [handler], [], os_names, os_versions)
|
541
|
+
result << [handler, found, pkg] if found
|
548
542
|
end
|
549
543
|
|
550
544
|
# Recursive resolutions
|
551
|
-
found, pkg = partition_osdep_entry(
|
545
|
+
found, pkg = partition_osdep_entry(
|
546
|
+
name, dep_def, ['osdep'], [], os_names, os_versions)
|
552
547
|
if found
|
553
548
|
if resolve_recursive
|
554
549
|
pkg.each do |pkg_name|
|
555
550
|
resolved = resolve_package(pkg_name)
|
556
|
-
|
557
|
-
raise InvalidRecursiveStatement, "the '#{name}' osdep
|
551
|
+
unless resolved
|
552
|
+
raise InvalidRecursiveStatement, "the '#{name}' osdep "\
|
553
|
+
"refers to another osdep, '#{pkg_name}', which "\
|
554
|
+
"does not seem to exist"
|
558
555
|
end
|
559
556
|
result.concat(resolved)
|
560
557
|
end
|
@@ -641,66 +638,20 @@ def partition_osdep_entry(osdep_name, dep_def, handler_names, excluded, *keys)
|
|
641
638
|
found_keys = Hash.new
|
642
639
|
Array(dep_def).each do |names, values|
|
643
640
|
if !values
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
found = true if !handler_names
|
648
|
-
elsif names == 'nonexistent'
|
649
|
-
nonexistent = true if !handler_names
|
650
|
-
elsif !handler_names && names.kind_of?(Array)
|
651
|
-
result.concat(result)
|
652
|
-
found = true
|
653
|
-
elsif names.respond_to?(:to_str)
|
654
|
-
if excluded.include?(names)
|
655
|
-
elsif handler_names && handler_names.include?(names)
|
656
|
-
result << osdep_name
|
657
|
-
found = true
|
658
|
-
elsif !handler_names
|
659
|
-
result << names
|
660
|
-
found = true
|
661
|
-
end
|
662
|
-
elsif names.respond_to?(:to_hash)
|
663
|
-
rec_found, rec_result = partition_osdep_entry(osdep_name, names, handler_names, excluded, keys, *additional_keys)
|
664
|
-
if rec_found == FOUND_NONEXISTENT then nonexistent = true
|
665
|
-
elsif rec_found == FOUND_PACKAGES then found = true
|
666
|
-
end
|
667
|
-
result.concat(rec_result)
|
668
|
-
end
|
641
|
+
entry_found, entry_nonexistent, entry_names =
|
642
|
+
partition_osdep_raw_array_entry(names, osdep_name,
|
643
|
+
handler_names, excluded, keys, additional_keys)
|
669
644
|
else
|
670
|
-
|
671
|
-
names
|
672
|
-
|
673
|
-
|
674
|
-
if handler_names
|
675
|
-
if matching_name = handler_names.find { |k| names.any? { |name_tag| k == name_tag.downcase } }
|
676
|
-
rec_found, rec_result = partition_osdep_entry(osdep_name, values, nil, excluded, keys, *additional_keys)
|
677
|
-
if rec_found == FOUND_NONEXISTENT then nonexistent = true
|
678
|
-
elsif rec_found == FOUND_PACKAGES then found = true
|
679
|
-
end
|
680
|
-
result.concat(rec_result)
|
681
|
-
end
|
682
|
-
end
|
683
|
-
|
684
|
-
matching_name = keys.find { |k| names.any? { |name_tag| k == name_tag.downcase } }
|
685
|
-
if matching_name
|
686
|
-
rec_found, rec_result = partition_osdep_entry(osdep_name, values, handler_names, excluded, *additional_keys)
|
687
|
-
# We only consider the first highest-priority entry,
|
688
|
-
# regardless of whether it has some packages for us or
|
689
|
-
# not
|
690
|
-
idx = keys.index(matching_name)
|
691
|
-
if !rec_found
|
692
|
-
if !found_keys.has_key?(idx)
|
693
|
-
found_keys[idx] = nil
|
694
|
-
end
|
695
|
-
else
|
696
|
-
found_keys[idx] ||= [0, []]
|
697
|
-
found_keys[idx][0] += rec_found
|
698
|
-
found_keys[idx][1].concat(rec_result)
|
699
|
-
end
|
700
|
-
end
|
645
|
+
entry_found, entry_nonexistent, entry_names =
|
646
|
+
partition_osdep_map_entry(names, values, osdep_name,
|
647
|
+
handler_names, excluded, keys, found_keys, additional_keys)
|
701
648
|
end
|
649
|
+
found ||= entry_found
|
650
|
+
nonexistent ||= entry_nonexistent
|
651
|
+
result.concat(entry_names)
|
702
652
|
end
|
703
|
-
|
653
|
+
|
654
|
+
first_entry = found_keys.keys.min
|
704
655
|
found_keys = found_keys[first_entry]
|
705
656
|
if found_keys
|
706
657
|
if found_keys[0] > 0
|
@@ -717,13 +668,91 @@ def partition_osdep_entry(osdep_name, dep_def, handler_names, excluded, *keys)
|
|
717
668
|
else false
|
718
669
|
end
|
719
670
|
|
720
|
-
|
671
|
+
[found, result]
|
672
|
+
end
|
673
|
+
|
674
|
+
def partition_osdep_raw_array_entry(names, osdep_name, handler_names,
|
675
|
+
excluded, keys, additional_keys)
|
676
|
+
have_handler_names = true if handler_names
|
677
|
+
|
678
|
+
# Raw array of packages. Possible only if we are not at toplevel
|
679
|
+
# (i.e. if we already have a handler)
|
680
|
+
if names == 'ignore'
|
681
|
+
[!have_handler_names, false, []]
|
682
|
+
elsif names == 'nonexistent'
|
683
|
+
[false, !have_handler_names, []]
|
684
|
+
elsif !handler_names && names.kind_of?(Array)
|
685
|
+
[true, false, names]
|
686
|
+
elsif names.respond_to?(:to_str)
|
687
|
+
if excluded.include?(names)
|
688
|
+
[false, false, []]
|
689
|
+
elsif handler_names&.include?(names)
|
690
|
+
[true, false, [osdep_name]]
|
691
|
+
elsif !handler_names
|
692
|
+
[true, false, [names]]
|
693
|
+
else
|
694
|
+
[false, false, []]
|
695
|
+
end
|
696
|
+
elsif names.respond_to?(:to_hash)
|
697
|
+
rec_found, rec_result = partition_osdep_entry(osdep_name,
|
698
|
+
names, handler_names, excluded, keys, *additional_keys)
|
699
|
+
if rec_found == FOUND_NONEXISTENT
|
700
|
+
[false, true, rec_result]
|
701
|
+
elsif rec_found == FOUND_PACKAGES
|
702
|
+
[true, false, rec_result]
|
703
|
+
else
|
704
|
+
[false, false, []]
|
705
|
+
end
|
706
|
+
else
|
707
|
+
[false, false, []]
|
708
|
+
end
|
709
|
+
end
|
710
|
+
|
711
|
+
def partition_osdep_map_entry(names, values, osdep_name, handler_names,
|
712
|
+
excluded, keys, found_keys, additional_keys)
|
713
|
+
# names could be an array already
|
714
|
+
names = names.split(',') if names.respond_to?(:to_str)
|
715
|
+
result = [false, false, []]
|
716
|
+
|
717
|
+
if handler_names
|
718
|
+
matching_handler = handler_names.
|
719
|
+
find { |k| names.any? { |name_tag| k == name_tag.downcase } }
|
720
|
+
if matching_handler
|
721
|
+
rec_found, rec_result = partition_osdep_entry(
|
722
|
+
osdep_name, values, nil, excluded, keys, *additional_keys)
|
723
|
+
if rec_found == FOUND_NONEXISTENT
|
724
|
+
result = [false, true, rec_result]
|
725
|
+
elsif rec_found == FOUND_PACKAGES
|
726
|
+
result = [true, false, rec_result]
|
727
|
+
end
|
728
|
+
end
|
729
|
+
end
|
730
|
+
|
731
|
+
matching_name = keys.
|
732
|
+
find { |k| names.any? { |name_tag| k == name_tag.downcase } }
|
733
|
+
return result unless matching_name
|
734
|
+
|
735
|
+
rec_found, rec_result = partition_osdep_entry(
|
736
|
+
osdep_name, values, handler_names, excluded, *additional_keys)
|
737
|
+
# We only consider the first highest-priority entry,
|
738
|
+
# regardless of whether it has some packages for us or
|
739
|
+
# not
|
740
|
+
idx = keys.index(matching_name)
|
741
|
+
if !rec_found
|
742
|
+
found_keys[idx] = nil unless found_keys.key?(idx)
|
743
|
+
else
|
744
|
+
found_keys[idx] ||= [0, []]
|
745
|
+
found_keys[idx][0] += rec_found
|
746
|
+
found_keys[idx][1].concat(rec_result)
|
747
|
+
end
|
748
|
+
result
|
721
749
|
end
|
722
750
|
|
723
751
|
# Resolves the given OS dependencies into the actual packages that need
|
724
752
|
# to be installed on this particular OS.
|
725
753
|
#
|
726
|
-
# @param [Array<String>] dependencies the list of osdep names that
|
754
|
+
# @param [Array<String>] dependencies the list of osdep names that
|
755
|
+
# should be resolved
|
727
756
|
# @return [Array<#install,Array<String>>] the set of packages, grouped
|
728
757
|
# by the package handlers that should be used to install them
|
729
758
|
#
|
@@ -733,25 +762,33 @@ def resolve_os_packages(dependencies)
|
|
733
762
|
all_packages = []
|
734
763
|
dependencies.each do |name|
|
735
764
|
result = resolve_package(name)
|
736
|
-
|
765
|
+
unless result
|
737
766
|
path = resolve_name(name)
|
738
|
-
raise MissingOSDep.new, "there is no osdeps definition
|
767
|
+
raise MissingOSDep.new, "there is no osdeps definition "\
|
768
|
+
"for #{path.last} (search tree: #{path.join('->')})"
|
739
769
|
end
|
740
770
|
|
741
771
|
if result.empty?
|
742
772
|
os_names, os_versions = operating_system
|
743
773
|
if os_names.empty?
|
744
|
-
raise MissingOSDep.new, "there is an osdeps
|
774
|
+
raise MissingOSDep.new, "there is an osdeps "\
|
775
|
+
"definition for #{name}, but autoproj cannot "\
|
776
|
+
"detect the local operation system"
|
745
777
|
else
|
746
|
-
raise MissingOSDep.new, "there is an osdeps
|
778
|
+
raise MissingOSDep.new, "there is an osdeps "\
|
779
|
+
"definition for #{name}, but not for this "\
|
780
|
+
"operating system and version resp. "\
|
781
|
+
"#{os_names.join(', ')} and #{os_versions.join(', ')})"
|
747
782
|
end
|
748
783
|
end
|
749
784
|
|
750
785
|
result.each do |handler, status, packages|
|
751
786
|
if status == FOUND_NONEXISTENT
|
752
|
-
raise MissingOSDep.new, "there is an osdep
|
787
|
+
raise MissingOSDep.new, "there is an osdep "\
|
788
|
+
"definition for #{name}, and it explicitely "\
|
789
|
+
"states that this package does not exist on your OS"
|
753
790
|
end
|
754
|
-
if entry = all_packages.find { |h, _| h == handler }
|
791
|
+
if (entry = all_packages.find { |h, _| h == handler })
|
755
792
|
entry[1].concat(packages)
|
756
793
|
else
|
757
794
|
all_packages << [handler, packages.dup]
|
@@ -759,22 +796,22 @@ def resolve_os_packages(dependencies)
|
|
759
796
|
end
|
760
797
|
end
|
761
798
|
|
762
|
-
all_packages.delete_if do |
|
799
|
+
all_packages.delete_if do |_handler, pkg|
|
763
800
|
pkg.empty?
|
764
801
|
end
|
765
|
-
|
802
|
+
all_packages
|
766
803
|
end
|
767
804
|
|
768
805
|
# Returns true if the given name has an entry in the osdeps
|
769
806
|
def include?(name)
|
770
|
-
definitions.
|
807
|
+
definitions.key?(name)
|
771
808
|
end
|
772
809
|
|
773
810
|
# Returns true if +name+ is an acceptable OS package for this OS and
|
774
811
|
# version
|
775
812
|
def has?(name)
|
776
813
|
status = availability_of(name)
|
777
|
-
|
814
|
+
[AVAILABLE, IGNORE].include?(status)
|
778
815
|
end
|
779
816
|
|
780
817
|
# Value returned by #availability_of if the required package has no
|
@@ -809,9 +846,7 @@ def has?(name)
|
|
809
846
|
# be installed for it
|
810
847
|
def availability_of(name)
|
811
848
|
resolved = resolve_package(name)
|
812
|
-
|
813
|
-
return NO_PACKAGE
|
814
|
-
end
|
849
|
+
return NO_PACKAGE unless resolved
|
815
850
|
|
816
851
|
if resolved.empty?
|
817
852
|
if known_operating_system?
|
@@ -821,7 +856,9 @@ def availability_of(name)
|
|
821
856
|
end
|
822
857
|
end
|
823
858
|
|
824
|
-
resolved = resolved.find_all
|
859
|
+
resolved = resolved.find_all do |_, status, list|
|
860
|
+
status != FOUND_PACKAGES || !list.empty?
|
861
|
+
end
|
825
862
|
failed = resolved.find_all do |_, status, _|
|
826
863
|
status == FOUND_NONEXISTENT
|
827
864
|
end
|
@@ -837,4 +874,3 @@ def availability_of(name)
|
|
837
874
|
end
|
838
875
|
end
|
839
876
|
end
|
840
|
-
|