autoproj 1.5.8 → 1.6.0.rc1
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.
- data/History.txt +5 -0
- data/Rakefile +38 -35
- data/bin/autoproj +1 -1
- data/doc/guide/src/autoproj_bootstrap +337 -92
- data/doc/guide/src/package_sets/index.page +3 -1
- data/lib/autoproj/autobuild.rb +67 -19
- data/lib/autoproj/cmdline.rb +93 -9
- data/lib/autoproj/manifest.rb +3 -2
- data/lib/autoproj/options.rb +17 -7
- data/lib/autoproj/osdeps.rb +250 -82
- data/lib/autoproj/system.rb +24 -2
- data/lib/autoproj/version.rb +1 -1
- metadata +11 -8
@@ -25,7 +25,9 @@ Adding a package
|
|
25
25
|
|
26
26
|
Adding a package to a package set involves changing two files:
|
27
27
|
|
28
|
-
* the package set's autobuild file that declares what
|
28
|
+
* one of the package set's autobuild file that declares what packages there
|
29
|
+
are. Any file ending with .autobuild is loaded as an autobuild file by
|
30
|
+
autoproj.
|
29
31
|
* the package set's source.yml file that declares where to get it (version
|
30
32
|
control information)
|
31
33
|
|
data/lib/autoproj/autobuild.rb
CHANGED
@@ -3,6 +3,29 @@ require 'fileutils'
|
|
3
3
|
require 'autobuild'
|
4
4
|
require 'set'
|
5
5
|
|
6
|
+
def explicit_osdeps_selection(name)
|
7
|
+
if !Autoproj.declared_option?("osdeps_#{name}")
|
8
|
+
if Autoproj.has_config_key?("osdeps_#{name}")
|
9
|
+
doc_string = "install #{name} from source ?"
|
10
|
+
else
|
11
|
+
# Declare the option
|
12
|
+
doc_string =<<-EOT
|
13
|
+
The #{name} package is listed as a dependency of #{self.name}. It is listed as an operating
|
14
|
+
system package for other operating systems than yours, and is also listed as a source package.
|
15
|
+
Since you requested manual updates, I have to ask you:
|
16
|
+
|
17
|
+
Do you want me to build #{name} from source ? If you say 'no', you will have to install it yourself.
|
18
|
+
EOT
|
19
|
+
end
|
20
|
+
|
21
|
+
Autoproj.configuration_option(
|
22
|
+
"osdeps_#{name}", "boolean",
|
23
|
+
:default => "yes",
|
24
|
+
:doc => doc_string)
|
25
|
+
end
|
26
|
+
!Autoproj.user_config("osdeps_#{name}")
|
27
|
+
end
|
28
|
+
|
6
29
|
module Autobuild
|
7
30
|
class Package
|
8
31
|
def autoproj_name # :nodoc:
|
@@ -11,23 +34,40 @@ module Autobuild
|
|
11
34
|
|
12
35
|
alias __depends_on__ depends_on
|
13
36
|
def depends_on(name)
|
14
|
-
explicit_selection
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
37
|
+
explicit_selection = Autoproj.manifest.explicitly_selected_package?(name)
|
38
|
+
osdeps_availability = Autoproj.osdeps.availability_of(name)
|
39
|
+
available_as_source = Autobuild::Package[name]
|
40
|
+
|
41
|
+
# Prefer OS packages to source packages
|
42
|
+
if !explicit_selection
|
43
|
+
if osdeps_availability == Autoproj::OSDependencies::AVAILABLE
|
44
|
+
@os_packages ||= Set.new
|
45
|
+
@os_packages << name
|
46
|
+
return
|
47
|
+
end
|
48
|
+
|
49
|
+
if osdeps_availability == Autoproj::OSDependencies::UNKNOWN_OS
|
50
|
+
# If we can't handle that OS, but other OSes have a
|
51
|
+
# definition for it, we assume that it can be installed as
|
52
|
+
# an external package. However, if it is also available as a
|
53
|
+
# source package, prompt the user
|
54
|
+
if !available_as_source || explicit_osdeps_selection(name)
|
55
|
+
@os_packages ||= Set.new
|
56
|
+
@os_packages << name
|
57
|
+
return
|
28
58
|
end
|
29
59
|
end
|
60
|
+
|
61
|
+
if !available_as_source
|
62
|
+
# Call osdeps to get a proper error message
|
63
|
+
osdeps, gems = Autoproj.osdeps.partition_packages([name].to_set, name => [self.name])
|
64
|
+
Autoproj.osdeps.resolve_os_dependencies(osdeps)
|
65
|
+
# Should never reach further than that
|
66
|
+
end
|
30
67
|
end
|
68
|
+
|
69
|
+
|
70
|
+
__depends_on__(name) # to get the error message
|
31
71
|
end
|
32
72
|
|
33
73
|
def depends_on_os_package(name)
|
@@ -83,12 +123,18 @@ module Autoproj
|
|
83
123
|
def self.filter_load_exception(error, source, path)
|
84
124
|
raise error if Autoproj.verbose
|
85
125
|
rx_path = Regexp.quote(path)
|
86
|
-
error_line = error.backtrace.find { |l| l =~ /#{rx_path}/ }
|
87
|
-
|
88
|
-
|
89
|
-
|
126
|
+
if error_line = error.backtrace.find { |l| l =~ /#{rx_path}/ }
|
127
|
+
if line_number = Integer(/#{rx_path}:(\d+)/.match(error_line)[1])
|
128
|
+
line_number = "#{line_number}:"
|
129
|
+
end
|
130
|
+
|
131
|
+
if source.local?
|
132
|
+
raise ConfigError, "#{path}:#{line_number} #{error.message}", error.backtrace
|
133
|
+
else
|
134
|
+
raise ConfigError, "#{File.basename(path)}(source=#{source.name}):#{line_number} #{error.message}", error.backtrace
|
135
|
+
end
|
90
136
|
else
|
91
|
-
raise
|
137
|
+
raise error
|
92
138
|
end
|
93
139
|
end
|
94
140
|
|
@@ -98,6 +144,8 @@ module Autoproj
|
|
98
144
|
@file_stack.push([source, File.basename(path)])
|
99
145
|
begin
|
100
146
|
Kernel.load path
|
147
|
+
rescue ConfigError => e
|
148
|
+
raise
|
101
149
|
rescue Exception => e
|
102
150
|
filter_load_exception(e, source, path)
|
103
151
|
end
|
data/lib/autoproj/cmdline.rb
CHANGED
@@ -20,12 +20,68 @@ module Autoproj
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
def self.color(*args)
|
24
|
+
console.color(*args)
|
25
|
+
end
|
26
|
+
|
23
27
|
# Displays a warning message
|
24
28
|
def self.warn(message)
|
25
29
|
Autoproj.progress(" WARN: #{message}", :magenta)
|
26
30
|
end
|
27
31
|
|
28
32
|
module CmdLine
|
33
|
+
def self.handle_automatic_osdeps
|
34
|
+
if !Autoproj.has_config_key?('automatic_osdeps') && ENV['AUTOPROJ_AUTOMATIC_OSDEPS']
|
35
|
+
mode = ENV['AUTOPROJ_AUTOMATIC_OSDEPS']
|
36
|
+
mode =
|
37
|
+
if mode == 'true' then Autoproj::OSDependencies::AUTOMATIC
|
38
|
+
elsif mode == 'false' then Autoproj::OSDependencies::MANUAL
|
39
|
+
elsif mode == 'wait' then Autoproj::OSDependencies::WAIT
|
40
|
+
else Autoproj::OSDependencies::ASK
|
41
|
+
end
|
42
|
+
|
43
|
+
Autoproj.change_option('automatic_osdeps', mode, true)
|
44
|
+
end
|
45
|
+
|
46
|
+
if Autoproj.has_config_key?("automatic_osdeps")
|
47
|
+
doc_string = "Should autoproj handle the OS package installation automatically (yes, no, wait or ask) ?"
|
48
|
+
else
|
49
|
+
# Ask the user for the automatic_osdeps option
|
50
|
+
doc_string =<<-EOT
|
51
|
+
#{color("Should autoproj handle the OS package installation automatically (yes, no, wait or ask) ?", :bold)}
|
52
|
+
If you say "no", the list of OS dependencies that need to be installed will be listed,
|
53
|
+
and autoproj will go on, assuming that you have installed them yourself. If you say
|
54
|
+
"ask", you will be prompted each time a package needs to be installed. Finally, if you
|
55
|
+
say "wait", autoproj will simply wait for you to press ENTER to continue after it prompted
|
56
|
+
you for the dependencies.
|
57
|
+
|
58
|
+
This value can be changed anytime by calling an autoproj operation with the --reconfigure
|
59
|
+
option (e.g. autoproj update --reconfigure). Moreover, the "autoproj osdeps" call will
|
60
|
+
always allow you to install OS dependencies through autoproj.
|
61
|
+
|
62
|
+
EOT
|
63
|
+
doc_string = doc_string.strip
|
64
|
+
end
|
65
|
+
|
66
|
+
Autoproj.configuration_option 'automatic_osdeps', 'string',
|
67
|
+
:default => 'yes',
|
68
|
+
:doc => doc_string do |value|
|
69
|
+
begin
|
70
|
+
Autoproj::BuildOption.validate_boolean(value, Hash.new)
|
71
|
+
rescue Autoproj::InputError
|
72
|
+
if value.to_s == "ask"
|
73
|
+
:ask
|
74
|
+
elsif value.to_s == "wait"
|
75
|
+
:wait
|
76
|
+
else
|
77
|
+
raise Autoproj::InputError, "invalid value. Please answer 'yes', 'no', 'wait' or 'ask' -- without the quotes"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
Autoproj.user_config('automatic_osdeps')
|
83
|
+
end
|
84
|
+
|
29
85
|
def self.initialize
|
30
86
|
Autobuild::Reporting << Autoproj::Reporter.new
|
31
87
|
if mail_config[:to]
|
@@ -34,6 +90,10 @@ module Autoproj
|
|
34
90
|
|
35
91
|
Autoproj.load_config
|
36
92
|
|
93
|
+
if Autoproj.has_config_key?('prefix')
|
94
|
+
Autoproj.prefix = Autoproj.user_config('prefix')
|
95
|
+
end
|
96
|
+
|
37
97
|
# If we are under rubygems, check that the GEM_HOME is right ...
|
38
98
|
if $LOADED_FEATURES.any? { |l| l =~ /rubygems/ }
|
39
99
|
if ENV['GEM_HOME'] != Autoproj.gem_home
|
@@ -50,6 +110,8 @@ module Autoproj
|
|
50
110
|
Autobuild.srcdir = Autoproj.root_dir
|
51
111
|
Autobuild.logdir = File.join(Autobuild.prefix, 'log')
|
52
112
|
|
113
|
+
handle_automatic_osdeps
|
114
|
+
|
53
115
|
ruby = RbConfig::CONFIG['RUBY_INSTALL_NAME']
|
54
116
|
if ruby != 'ruby'
|
55
117
|
bindir = File.join(Autoproj.build_dir, 'bin')
|
@@ -282,6 +344,27 @@ module Autoproj
|
|
282
344
|
selected_packages
|
283
345
|
end
|
284
346
|
|
347
|
+
def self.verify_package_availability(pkg_name)
|
348
|
+
if reason = Autoproj.manifest.exclusion_reason(pkg_name)
|
349
|
+
raise ConfigError, "#{pkg_name} is excluded from the build: #{reason}"
|
350
|
+
end
|
351
|
+
pkg = Autobuild::Package[pkg_name]
|
352
|
+
if !pkg
|
353
|
+
raise ConfigError, "#{pkg_name} does not seem to exist"
|
354
|
+
end
|
355
|
+
|
356
|
+
# Verify that its dependencies are there, and add
|
357
|
+
# them to the selected_packages set so that they get
|
358
|
+
# imported as well
|
359
|
+
pkg.dependencies.each do |dep_name|
|
360
|
+
begin
|
361
|
+
verify_package_availability(dep_name)
|
362
|
+
rescue ConfigError => e
|
363
|
+
raise e, "#{pkg_name} depends on #{dep_name}, but #{e.message}"
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
285
368
|
def self.import_packages(selected_packages)
|
286
369
|
selected_packages = selected_packages.dup.
|
287
370
|
map do |pkg_name|
|
@@ -309,6 +392,7 @@ module Autoproj
|
|
309
392
|
Autobuild.do_update = old_update_flag
|
310
393
|
end
|
311
394
|
|
395
|
+
known_available_packages = Set.new
|
312
396
|
all_enabled_packages = Set.new
|
313
397
|
|
314
398
|
package_queue = selected_packages.dup
|
@@ -320,6 +404,12 @@ module Autoproj
|
|
320
404
|
delete_if { |pkg| all_enabled_packages.include?(pkg.name) }
|
321
405
|
all_enabled_packages |= current_packages.map(&:name).to_set
|
322
406
|
|
407
|
+
# Recursively check that no package in the selection depend on
|
408
|
+
# excluded packages
|
409
|
+
current_packages.each do |pkg|
|
410
|
+
verify_package_availability(pkg.name)
|
411
|
+
end
|
412
|
+
|
323
413
|
# We import first so that all packages can export the
|
324
414
|
# additional targets they provide.
|
325
415
|
current_packages.each do |pkg|
|
@@ -334,21 +424,14 @@ module Autoproj
|
|
334
424
|
end
|
335
425
|
|
336
426
|
current_packages.each do |pkg|
|
427
|
+
verify_package_availability(pkg.name)
|
337
428
|
Rake::Task["#{pkg.name}-prepare"].invoke
|
338
429
|
|
339
430
|
# Verify that its dependencies are there, and add
|
340
431
|
# them to the selected_packages set so that they get
|
341
432
|
# imported as well
|
342
433
|
pkg.dependencies.each do |dep_name|
|
343
|
-
|
344
|
-
raise ConfigError, "#{pkg.name} depends on #{dep_name}, which is excluded from the build: #{reason}"
|
345
|
-
end
|
346
|
-
dep_pkg = Autobuild::Package[dep_name]
|
347
|
-
if !dep_pkg
|
348
|
-
raise ConfigError, "#{pkg.name} depends on #{dep_name}, but it does not seem to exist"
|
349
|
-
end
|
350
|
-
|
351
|
-
package_queue << dep_pkg
|
434
|
+
package_queue << Autobuild::Package[dep_name]
|
352
435
|
end
|
353
436
|
end
|
354
437
|
end
|
@@ -630,6 +713,7 @@ where 'mode' is one of:
|
|
630
713
|
Autobuild.do_update = false
|
631
714
|
@update_os_dependencies = true
|
632
715
|
Autobuild.do_build = false
|
716
|
+
Autoproj::OSDependencies.force_osdeps = true
|
633
717
|
when "status"
|
634
718
|
@only_status = true
|
635
719
|
Autobuild.do_update = false
|
data/lib/autoproj/manifest.rb
CHANGED
@@ -938,6 +938,7 @@ module Autoproj
|
|
938
938
|
if dest != source.raw_local_dir
|
939
939
|
FileUtils.rm_f symlink_dest
|
940
940
|
end
|
941
|
+
FileUtils.ln_sf source.raw_local_dir, symlink_dest
|
941
942
|
else
|
942
943
|
FileUtils.rm_f symlink_dest
|
943
944
|
FileUtils.ln_sf source.raw_local_dir, symlink_dest
|
@@ -1151,9 +1152,9 @@ module Autoproj
|
|
1151
1152
|
begin
|
1152
1153
|
package.depends_on name
|
1153
1154
|
rescue Autobuild::ConfigException => e
|
1154
|
-
raise ConfigError, "manifest #{manifest_path} of #{package.name} from #{source.name} lists '#{name}' as dependency, which is listed in the layout but has no autobuild definition"
|
1155
|
+
raise ConfigError, "manifest #{manifest_path} of #{package.name} from #{source.name} lists '#{name}' as dependency, which is listed in the layout but has no autobuild definition", e.backtrace
|
1155
1156
|
rescue ConfigError => e
|
1156
|
-
raise ConfigError, "manifest #{manifest_path} of #{package.name} from #{source.name} lists '#{name}' as dependency, but it is neither a normal package nor an osdeps package. osdeps reports: #{e.message}"
|
1157
|
+
raise ConfigError, "manifest #{manifest_path} of #{package.name} from #{source.name} lists '#{name}' as dependency, but it is neither a normal package nor an osdeps package. osdeps reports: #{e.message}", e.backtrace
|
1157
1158
|
end
|
1158
1159
|
end
|
1159
1160
|
end
|
data/lib/autoproj/options.rb
CHANGED
@@ -23,12 +23,14 @@ module Autoproj
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def ask(current_value)
|
26
|
-
default_value =
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
default_value =
|
27
|
+
if current_value then current_value.to_s
|
28
|
+
elsif options[:default] then options[:default].to_str
|
29
|
+
else ''
|
30
|
+
end
|
31
|
+
|
32
|
+
STDOUT.print " #{doc} [#{default_value}] "
|
33
|
+
STDOUT.flush
|
32
34
|
answer = STDIN.readline.chomp
|
33
35
|
if answer == ''
|
34
36
|
answer = default_value
|
@@ -90,7 +92,11 @@ module Autoproj
|
|
90
92
|
value = configure(key)
|
91
93
|
else
|
92
94
|
if !seen
|
93
|
-
|
95
|
+
doc = @declared_options[key].doc
|
96
|
+
if doc[-1, 1] != "?"
|
97
|
+
doc = "#{doc}:"
|
98
|
+
end
|
99
|
+
Autoproj.progress " #{doc} #{value}"
|
94
100
|
@user_config[key] = [value, true]
|
95
101
|
end
|
96
102
|
value
|
@@ -102,6 +108,10 @@ module Autoproj
|
|
102
108
|
@declared_options[name] = BuildOption.new(name, type, options, validator)
|
103
109
|
end
|
104
110
|
|
111
|
+
def self.declared_option?(name)
|
112
|
+
@declared_options.has_key?(name)
|
113
|
+
end
|
114
|
+
|
105
115
|
def self.configure(option_name)
|
106
116
|
if opt = @declared_options[option_name]
|
107
117
|
if current_value = @user_config[option_name]
|
data/lib/autoproj/osdeps.rb
CHANGED
@@ -15,6 +15,8 @@ module Autoproj
|
|
15
15
|
|
16
16
|
class << self
|
17
17
|
attr_reader :aliases
|
18
|
+
attr_accessor :force_osdeps
|
19
|
+
attr_accessor :gem_with_prerelease
|
18
20
|
end
|
19
21
|
@aliases = Hash.new
|
20
22
|
|
@@ -142,11 +144,13 @@ module Autoproj
|
|
142
144
|
['gentoo', [version]]
|
143
145
|
elsif File.exists?('/etc/arch-release')
|
144
146
|
['arch', []]
|
145
|
-
else
|
146
|
-
raise ConfigError, "Unknown operating system"
|
147
147
|
end
|
148
148
|
end
|
149
149
|
|
150
|
+
if !@operating_system
|
151
|
+
return
|
152
|
+
end
|
153
|
+
|
150
154
|
# Normalize the names to lowercase
|
151
155
|
@operating_system =
|
152
156
|
[@operating_system[0].downcase,
|
@@ -182,62 +186,118 @@ module Autoproj
|
|
182
186
|
'arch' => 'pacman -Sy --noconfirm %s'
|
183
187
|
}
|
184
188
|
|
185
|
-
|
186
|
-
|
189
|
+
NO_PACKAGE = 0
|
190
|
+
WRONG_OS = 1
|
191
|
+
WRONG_OS_VERSION = 2
|
192
|
+
IGNORE = 3
|
193
|
+
PACKAGES = 4
|
194
|
+
SHELL_SNIPPET = 5
|
195
|
+
UNKNOWN_OS = 7
|
196
|
+
AVAILABLE = 10
|
197
|
+
|
198
|
+
# Check for the definition of +name+ for this operating system
|
187
199
|
#
|
188
|
-
#
|
189
|
-
|
200
|
+
# It can return
|
201
|
+
#
|
202
|
+
# NO_PACKAGE::
|
203
|
+
# there are no package definition for +name
|
204
|
+
# UNKNOWN_OS::
|
205
|
+
# this is not an OS autoproj knows how to deal with
|
206
|
+
# WRONG_OS::
|
207
|
+
# there are a package definition, but not for this OS
|
208
|
+
# WRONG_OS_VERSION::
|
209
|
+
# there is a package definition for this OS, but not for this
|
210
|
+
# particular version of the OS
|
211
|
+
# IGNORE::
|
212
|
+
# there is a package definition that told us to ignore the package
|
213
|
+
# [PACKAGES, definition]::
|
214
|
+
# +definition+ is an array of package names that this OS's package
|
215
|
+
# manager can understand
|
216
|
+
# [SHELL_SNIPPET, definition]::
|
217
|
+
# +definition+ is a string which is a shell snippet that will install
|
218
|
+
# the package
|
219
|
+
def resolve_package(name)
|
190
220
|
os_name, os_version = OSDependencies.operating_system
|
191
|
-
|
192
|
-
|
221
|
+
|
222
|
+
dep_def = definitions[name]
|
223
|
+
if !dep_def
|
224
|
+
return NO_PACKAGE
|
193
225
|
end
|
194
226
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
227
|
+
if !os_name
|
228
|
+
return UNKNOWN_OS
|
229
|
+
end
|
230
|
+
|
231
|
+
# Find a matching entry for the OS name
|
232
|
+
os_entry = dep_def.find do |name_list, data|
|
233
|
+
name_list.split(',').
|
234
|
+
map(&:downcase).
|
235
|
+
any? { |n| n == os_name }
|
236
|
+
end
|
237
|
+
|
238
|
+
if !os_entry
|
239
|
+
return WRONG_OS
|
240
|
+
end
|
241
|
+
|
242
|
+
data = os_entry.last
|
202
243
|
|
203
|
-
|
204
|
-
|
205
|
-
|
244
|
+
# This package does not need to be installed on this operating system (example: build tools on Gentoo)
|
245
|
+
if !data || data == "ignore"
|
246
|
+
return IGNORE
|
247
|
+
end
|
248
|
+
|
249
|
+
if data.kind_of?(Hash)
|
250
|
+
version_entry = data.find do |version_list, data|
|
251
|
+
version_list.to_s.split(',').
|
206
252
|
map(&:downcase).
|
207
|
-
any?
|
253
|
+
any? do |v|
|
254
|
+
os_version.any? { |osv| Regexp.new(v) =~ osv }
|
255
|
+
end
|
208
256
|
end
|
209
257
|
|
210
|
-
if !
|
211
|
-
|
258
|
+
if !version_entry
|
259
|
+
return WRONG_OS_VERSION
|
212
260
|
end
|
261
|
+
data = version_entry.last
|
262
|
+
end
|
213
263
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
264
|
+
if data.respond_to?(:to_ary)
|
265
|
+
return [PACKAGES, data]
|
266
|
+
elsif data.to_str =~ /\w+/
|
267
|
+
return [PACKAGES, [data.to_str]]
|
268
|
+
else
|
269
|
+
return [SHELL_SNIPPET, data.to_str]
|
270
|
+
end
|
271
|
+
end
|
218
272
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
end
|
226
|
-
end
|
273
|
+
# Resolves the given OS dependencies into the actual packages that need
|
274
|
+
# to be installed on this particular OS.
|
275
|
+
#
|
276
|
+
# Raises ConfigError if some packages can't be found
|
277
|
+
def resolve_os_dependencies(dependencies)
|
278
|
+
os_name, os_version = OSDependencies.operating_system
|
227
279
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
280
|
+
os_packages = []
|
281
|
+
shell_snippets = []
|
282
|
+
dependencies.each do |name|
|
283
|
+
result = resolve_package(name)
|
284
|
+
if result == NO_PACKAGE
|
285
|
+
raise ConfigError, "there is no osdeps definition for #{name}"
|
286
|
+
elsif result == WRONG_OS
|
287
|
+
raise ConfigError, "there is an osdeps definition for #{name}, but not for this operating system"
|
288
|
+
elsif result == WRONG_OS_VERSION
|
289
|
+
raise ConfigError, "there is an osdeps definition for #{name}, but no for this particular operating system version"
|
290
|
+
elsif result == IGNORE
|
291
|
+
next
|
292
|
+
elsif result[0] == PACKAGES
|
293
|
+
os_packages.concat(result[1])
|
294
|
+
elsif result[0] == SHELL_SNIPPET
|
295
|
+
shell_snippets << result[1]
|
232
296
|
end
|
297
|
+
end
|
233
298
|
|
234
|
-
|
235
|
-
|
236
|
-
elsif data.to_str =~ /\w+/
|
237
|
-
os_packages << data.to_str
|
238
|
-
else
|
239
|
-
shell_snippets << data.to_str
|
240
|
-
end
|
299
|
+
if !OS_PACKAGE_INSTALL.has_key?(os_name)
|
300
|
+
raise ConfigError, "I don't know how to install packages on #{os_name}"
|
241
301
|
end
|
242
302
|
|
243
303
|
return os_packages, shell_snippets
|
@@ -254,14 +314,27 @@ module Autoproj
|
|
254
314
|
"\n" + shell_snippets.join("\n")
|
255
315
|
end
|
256
316
|
|
257
|
-
# Returns true if
|
258
|
-
#
|
317
|
+
# Returns true if +name+ is an acceptable OS package for this OS and
|
318
|
+
# version
|
259
319
|
def has?(name)
|
320
|
+
availability_of(name) == AVAILABLE
|
321
|
+
end
|
322
|
+
|
323
|
+
# If +name+ is an osdeps that is available for this operating system,
|
324
|
+
# returns AVAILABLE. Otherwise, returns the same error code than
|
325
|
+
# resolve_package.
|
326
|
+
def availability_of(name)
|
260
327
|
osdeps, gemdeps = partition_packages([name].to_set)
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
328
|
+
if !osdeps.empty?
|
329
|
+
status = resolve_package(name)
|
330
|
+
if status.respond_to?(:to_ary) || status == IGNORE
|
331
|
+
AVAILABLE
|
332
|
+
else
|
333
|
+
status
|
334
|
+
end
|
335
|
+
else
|
336
|
+
AVAILABLE
|
337
|
+
end
|
265
338
|
end
|
266
339
|
|
267
340
|
# call-seq:
|
@@ -282,12 +355,10 @@ module Autoproj
|
|
282
355
|
package_set.to_set.each do |name|
|
283
356
|
pkg_def = definitions[name]
|
284
357
|
if !pkg_def
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
raise ConfigError, msg
|
358
|
+
# Error cases are taken care of later, because that is were
|
359
|
+
# the automatic/manual osdeps logic lies
|
360
|
+
osdeps << name
|
361
|
+
next
|
291
362
|
end
|
292
363
|
|
293
364
|
pkg_def = pkg_def.dup
|
@@ -298,6 +369,9 @@ module Autoproj
|
|
298
369
|
when "gem" then
|
299
370
|
gems << name
|
300
371
|
else
|
372
|
+
# This is *not* handled later, as is the absence of a
|
373
|
+
# package definition. The reason is that it is a bad
|
374
|
+
# configuration file, and should be fixed by the user
|
301
375
|
raise ConfigError, "unknown OS-independent package management type #{pkg_def} for #{name}"
|
302
376
|
end
|
303
377
|
else
|
@@ -328,19 +402,123 @@ module Autoproj
|
|
328
402
|
end
|
329
403
|
end
|
330
404
|
|
405
|
+
def filter_uptodate_gems(gems)
|
406
|
+
Autobuild.progress "looking for RubyGems updates"
|
407
|
+
|
408
|
+
# Don't install gems that are already there ...
|
409
|
+
gems = gems.dup
|
410
|
+
gems.delete_if do |name|
|
411
|
+
version_requirements = Gem::Requirement.default
|
412
|
+
installed = Gem.source_index.find_name(name, version_requirements)
|
413
|
+
if !installed.empty? && Autobuild.do_update
|
414
|
+
# Look if we can update the package ...
|
415
|
+
dep = Gem::Dependency.new(name, version_requirements)
|
416
|
+
available = gem_fetcher.find_matching(dep)
|
417
|
+
installed_version = installed.map(&:version).max
|
418
|
+
available_version = available.map { |(name, v), source| v }.max
|
419
|
+
needs_update = (available_version > installed_version)
|
420
|
+
!needs_update
|
421
|
+
else
|
422
|
+
!installed.empty?
|
423
|
+
end
|
424
|
+
end
|
425
|
+
gems
|
426
|
+
end
|
427
|
+
|
428
|
+
AUTOMATIC = true
|
429
|
+
MANUAL = false
|
430
|
+
WAIT = :wait
|
431
|
+
ASK = :ask
|
432
|
+
|
433
|
+
def automatic_osdeps_mode
|
434
|
+
if mode = ENV['AUTOPROJ_AUTOMATIC_OSDEPS']
|
435
|
+
mode =
|
436
|
+
if mode == 'true' then AUTOMATIC
|
437
|
+
elsif mode == 'false' then MANUAL
|
438
|
+
elsif mode == 'wait' then WAIT
|
439
|
+
else ASK
|
440
|
+
end
|
441
|
+
Autoproj.change_option('automatic_osdeps', mode, true)
|
442
|
+
mode
|
443
|
+
else
|
444
|
+
Autoproj.user_config('automatic_osdeps')
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
331
448
|
# Requests the installation of the given set of packages
|
332
449
|
def install(packages, package_osdeps = Hash.new)
|
450
|
+
os_def = OSDependencies.operating_system
|
333
451
|
osdeps, gems = partition_packages(packages, package_osdeps)
|
452
|
+
gems = filter_uptodate_gems(gems)
|
453
|
+
if osdeps.empty? && gems.empty?
|
454
|
+
return
|
455
|
+
end
|
456
|
+
|
457
|
+
if automatic_osdeps_mode == AUTOMATIC && !os_def && !osdeps.empty?
|
458
|
+
puts
|
459
|
+
puts Autoproj.color("==============================", :bold)
|
460
|
+
puts Autoproj.color("The packages that will be built require some other software to be installed", :bold)
|
461
|
+
puts " " + osdeps.join("\n ")
|
462
|
+
puts Autoproj.color("==============================", :bold)
|
463
|
+
puts
|
464
|
+
end
|
465
|
+
|
466
|
+
if !OSDependencies.force_osdeps && automatic_osdeps_mode != AUTOMATIC
|
467
|
+
puts
|
468
|
+
puts Autoproj.color("==============================", :bold)
|
469
|
+
puts Autoproj.color("The packages that will be built require some other software to be installed", :bold)
|
470
|
+
puts
|
471
|
+
if !osdeps.empty?
|
472
|
+
puts "From the operating system:"
|
473
|
+
puts " " + osdeps.join("\n ")
|
474
|
+
puts
|
475
|
+
end
|
476
|
+
if !gems.empty?
|
477
|
+
puts "From RubyGems:"
|
478
|
+
puts " " + gems.join("\n ")
|
479
|
+
puts
|
480
|
+
end
|
481
|
+
|
482
|
+
if automatic_osdeps_mode == ASK
|
483
|
+
print "Should I install these packages ? [yes] "
|
484
|
+
STDOUT.flush
|
485
|
+
do_osdeps = nil
|
486
|
+
while do_osdeps.nil?
|
487
|
+
answer = STDIN.readline.chomp
|
488
|
+
if answer == ''
|
489
|
+
do_osdeps = true
|
490
|
+
elsif answer == "no"
|
491
|
+
do_osdeps = false
|
492
|
+
elsif answer == 'yes'
|
493
|
+
do_osdeps = true
|
494
|
+
else
|
495
|
+
print "invalid answer. Please answer with 'yes' or 'no' "
|
496
|
+
STDOUT.flush
|
497
|
+
end
|
498
|
+
end
|
499
|
+
else
|
500
|
+
puts "Since you requested autoproj to not handle the osdeps automatically, you have to"
|
501
|
+
puts "do it yourself. Alternatively, you can run 'autoproj osdeps' and/or change to"
|
502
|
+
puts "automatic osdeps handling by running an autoproj operation with the --reconfigure"
|
503
|
+
puts "option (e.g. autoproj build --reconfigure)"
|
504
|
+
puts Autoproj.color("==============================", :bold)
|
505
|
+
puts
|
506
|
+
|
507
|
+
if automatic_osdeps_mode == WAIT
|
508
|
+
print "Press ENTER to continue "
|
509
|
+
STDOUT.flush
|
510
|
+
STDIN.readline
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
if !do_osdeps
|
515
|
+
return
|
516
|
+
end
|
517
|
+
end
|
334
518
|
|
335
519
|
did_something = false
|
336
520
|
|
337
|
-
|
338
|
-
# Unfortunately, this is C++ code and I don't want to install the
|
339
|
-
# whole ROS stack just for rosdep ...
|
340
|
-
#
|
341
|
-
# So, for now, reimplement rosdep by ourselves. Given how things
|
342
|
-
# are done, this is actually not so hard.
|
343
|
-
if !osdeps.empty?
|
521
|
+
if os_def && !osdeps.empty?
|
344
522
|
shell_script = generate_os_script(osdeps)
|
345
523
|
if Autoproj.verbose
|
346
524
|
Autoproj.progress "Installing non-ruby OS dependencies with"
|
@@ -360,35 +538,25 @@ module Autoproj
|
|
360
538
|
end
|
361
539
|
|
362
540
|
if !gems.empty?
|
363
|
-
|
364
|
-
# Don't install gems that are already there ...
|
365
|
-
gems.delete_if do |name|
|
366
|
-
version_requirements = Gem::Requirement.default
|
367
|
-
installed = Gem.source_index.find_name(name, version_requirements)
|
368
|
-
if !installed.empty? && Autobuild.do_update
|
369
|
-
# Look if we can update the package ...
|
370
|
-
dep = Gem::Dependency.new(name, version_requirements)
|
371
|
-
available = gem_fetcher.find_matching(dep)
|
372
|
-
installed_version = installed.map(&:version).max
|
373
|
-
available_version = available.map { |(name, v), source| v }.max
|
374
|
-
needs_update = (available_version > installed_version)
|
375
|
-
!needs_update
|
376
|
-
else
|
377
|
-
!installed.empty?
|
378
|
-
end
|
379
|
-
end
|
541
|
+
gems = filter_uptodate_gems(gems)
|
380
542
|
end
|
381
543
|
|
382
544
|
# Now install what is left
|
383
545
|
if !gems.empty?
|
384
546
|
guess_gem_program
|
385
|
-
|
386
547
|
if Autoproj.verbose
|
387
548
|
Autoproj.progress "Installing rubygems dependencies with"
|
388
549
|
Autoproj.progress "gem install #{gems.join(" ")}"
|
389
550
|
end
|
551
|
+
|
552
|
+
cmdline = [Autobuild.tool('gem'), 'install']
|
553
|
+
if Autobuild::OSDependencies.gem_with_prerelease
|
554
|
+
cmdline << "--prerelease"
|
555
|
+
end
|
556
|
+
cmdline.concat(gems)
|
557
|
+
|
390
558
|
Autobuild.progress "installing/updating RubyGems dependencies: #{gems.join(", ")}"
|
391
|
-
Autobuild::Subprocess.run 'autoproj', 'osdeps',
|
559
|
+
Autobuild::Subprocess.run 'autoproj', 'osdeps', *cmdline
|
392
560
|
did_something ||= true
|
393
561
|
end
|
394
562
|
|