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