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.
@@ -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 type of package it is and
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
 
@@ -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 = Autoproj.manifest.explicitly_selected_package?(name)
15
- if Autoproj.osdeps.has?(name) && !explicit_selection
16
- @os_packages ||= Set.new
17
- @os_packages << name
18
- else
19
- begin
20
- __depends_on__(name)
21
- rescue Exception => e
22
- if explicit_selection
23
- raise e
24
- else
25
- # Re-call osdeps to get a proper error message
26
- osdeps, gems = Autoproj.osdeps.partition_packages([name].to_set, name => [self.name])
27
- Autoproj.osdeps.resolve_os_dependencies(osdeps)
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
- line_number = Integer(/#{rx_path}:(\d+)/.match(error_line)[1])
88
- if source.local?
89
- raise ConfigError, "#{path}:#{line_number}: #{error.message}", error.backtrace
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 ConfigError, "#{File.basename(path)}(source=#{source.name}):#{line_number}: #{error.message}", error.backtrace
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
@@ -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
- if reason = Autoproj.manifest.exclusion_reason(dep_name)
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
@@ -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
@@ -23,12 +23,14 @@ module Autoproj
23
23
  end
24
24
 
25
25
  def ask(current_value)
26
- default_value = if current_value then current_value.to_s
27
- elsif options[:default] then options[:default].to_str
28
- else ''
29
- end
30
-
31
- STDERR.print " #{doc} [#{default_value}] "
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
- Autoproj.progress " #{@declared_options[key].doc}: #{value}"
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]
@@ -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
- # Resolves the given OS dependencies into the actual packages that need
186
- # to be installed on this particular OS.
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
- # Raises ConfigError if some packages can't be found
189
- def resolve_os_dependencies(dependencies)
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
- if !OS_PACKAGE_INSTALL.has_key?(os_name)
192
- raise ConfigError, "I don't know how to install packages on #{os_name}"
221
+
222
+ dep_def = definitions[name]
223
+ if !dep_def
224
+ return NO_PACKAGE
193
225
  end
194
226
 
195
- os_packages = []
196
- shell_snippets = []
197
- dependencies.each do |name|
198
- dep_def = definitions[name]
199
- if !dep_def
200
- raise ConfigError, "I don't know how to install '#{name}'"
201
- end
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
- # Find a matching entry for the OS name
204
- os_entry = dep_def.find do |name_list, data|
205
- name_list.split(',').
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? { |n| n == os_name }
253
+ any? do |v|
254
+ os_version.any? { |osv| Regexp.new(v) =~ osv }
255
+ end
208
256
  end
209
257
 
210
- if !os_entry
211
- raise ConfigError, "I don't know how to install '#{name}' on #{os_name}"
258
+ if !version_entry
259
+ return WRONG_OS_VERSION
212
260
  end
261
+ data = version_entry.last
262
+ end
213
263
 
214
- data = os_entry.last
215
-
216
- # This package does not need to be installed on this operating system (example: build tools on Gentoo)
217
- next if !data || data == "ignore"
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
- if data.kind_of?(Hash)
220
- version_entry = data.find do |version_list, data|
221
- version_list.to_s.split(',').
222
- map(&:downcase).
223
- any? do |v|
224
- os_version.any? { |osv| Regexp.new(v) =~ osv }
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
- if !version_entry
229
- raise ConfigError, "I don't know how to install '#{name}' on this specific version of #{os_name} (#{os_version.join(", ")})"
230
- end
231
- data = version_entry.last
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
- if data.respond_to?(:to_ary)
235
- os_packages.concat data.to_ary
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 there is an operating-system package with that name,
258
- # and false otherwise
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
- resolve_os_dependencies(osdeps)
262
- true
263
- rescue ConfigError
264
- false
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
- msg = "I know nothing about a prepackaged software called '#{name}'"
286
- if pkg_names = package_osdeps[name]
287
- msg += ", it is listed as dependency of the following package(s): #{pkg_names.join(", ")}"
288
- end
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
- # Ideally, we would feed the OS dependencies to rosdep.
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
- Autobuild.progress "looking for RubyGems updates"
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', Autobuild.tool('gem'), 'install', *gems
559
+ Autobuild::Subprocess.run 'autoproj', 'osdeps', *cmdline
392
560
  did_something ||= true
393
561
  end
394
562