autoproj 2.0.0.rc31 → 2.0.0.rc32

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/lib/autoproj.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "enumerator"
2
2
  require 'utilrb/module/attr_predicate'
3
+ require 'pathname'
3
4
  require 'concurrent'
4
5
  require 'autobuild'
5
6
  require 'autoproj/base'
@@ -206,49 +206,61 @@ def parallel_import_level=(level)
206
206
  set('parallel_import_level', level)
207
207
  end
208
208
 
209
- def private_bundler?
210
- !!get('private_bundler', false)
209
+ # The user-wide place where RubyGems installs gems
210
+ def self.dot_gem_dir
211
+ File.join(Gem.user_home, ".gem")
211
212
  end
212
213
 
213
- def bundler_gem_home
214
- get('private_bundler', Gem.user_dir)
214
+ # The Ruby platform and version-specific subdirectory used by bundler and rubygem
215
+ def self.gems_path_suffix
216
+ @gems_path_suffix ||= Pathname.new(Gem.user_dir).
217
+ relative_path_from(Pathname.new(dot_gem_dir)).to_s
215
218
  end
216
219
 
217
- def private_autoproj?
218
- !!get('private_autoproj', false)
220
+ # The gem install root into which the bundler and autoproj gems, as well
221
+ # as autoproj's dependencies, are installed
222
+ #
223
+ # Note that while this setting is separated from the other gems path,
224
+ # the only way to reliably isolate the gems of an autoproj workspace is
225
+ # to separate both the autoproj gems and the workspace gems.
226
+ #
227
+ # The gems are actually installed under a platform and version-specific
228
+ # subdirectory (returned by {#gems_path_suffix})
229
+ #
230
+ # @return [String]
231
+ def autoproj_install_path
232
+ get('autoproj_install_path')
219
233
  end
220
234
 
235
+ # The GEM_HOME into which the autoproj gem and its dependencies are installed
236
+ #
237
+ # @return [String]
221
238
  def autoproj_gem_home
222
- get('private_autoproj', Gem.user_dir)
223
- end
224
-
225
- def private_gems?
226
- !!get('private_gems', false)
239
+ File.join(autoproj_install_path, self.class.gems_path_suffix)
227
240
  end
228
241
 
229
- # The path provided to bundler to install the gems
230
- def gems_bundler_path(ws)
231
- value = get('private_gems', false)
232
- if value.respond_to?(:to_str)
233
- value
234
- elsif value
235
- default = File.join(ws.prefix_dir, 'gems')
236
- set('private_gems', default)
237
- default
238
- end
242
+ # The gem install root into which the workspace gems are installed
243
+ #
244
+ # Note that while this setting is separated from the other gems path,
245
+ # the only way to reliably isolate the gems of an autoproj workspace is
246
+ # to separate both the autoproj gems and the workspace gems. This is why
247
+ # there are only --public and --private settings in autoproj_install
248
+ #
249
+ # The gems are actually installed under a platform and version-specific
250
+ # subdirectory (returned by {#gems_path_suffix})
251
+ #
252
+ # @param [Workspace] ws the workspace whose gems are being considered
253
+ # @return [String]
254
+ def gems_install_path(ws)
255
+ File.expand_path(get('gems_install_path'), ws.prefix_dir)
239
256
  end
240
257
 
241
- # The GEM_HOME derived from {#gems_bundler_path}
258
+ # The GEM_HOME into which the workspace gems are installed
242
259
  #
243
- # RubyGems and Bundler install gems in a subdirectory specific to the
244
- # Ruby platform and version. This adds the relevant suffix to
245
- # {#gems_bundler_path}
260
+ # @param [Workspace] ws the workspace whose gems are being considered
261
+ # @return [String]
246
262
  def gems_gem_home(ws)
247
- base_path = gems_bundler_path(ws) || File.join(Gem.user_dir, '.gem')
248
- path_suffix = Pathname.new(Gem.user_dir).
249
- relative_path_from(Pathname.new(File.join(Gem.user_home, '.gem'))).
250
- to_s
251
- File.join(base_path, path_suffix)
263
+ File.join(gems_install_path(ws), self.class.gems_path_suffix)
252
264
  end
253
265
 
254
266
  # The full path to the expected ruby executable
@@ -26,6 +26,8 @@ class UnexpectedBinstub < RuntimeError; end
26
26
  attr_reader :autoproj_options
27
27
  # The Ruby interpreter we use for this install
28
28
  attr_reader :ruby_executable
29
+ # The URL of the source to be used to get gems
30
+ attr_accessor :gem_source
29
31
 
30
32
  def initialize(root_dir)
31
33
  @root_dir = root_dir
@@ -34,6 +36,7 @@ def initialize(root_dir)
34
36
  else
35
37
  @gemfile = default_gemfile_contents
36
38
  end
39
+ @gem_source = "https://rubygems.org"
37
40
 
38
41
  @autoproj_options = Array.new
39
42
 
@@ -50,6 +53,10 @@ def initialize(root_dir)
50
53
  end
51
54
  @ruby_executable = config['ruby_executable']
52
55
  @local = false
56
+
57
+ default_gem_path = File.join(Dir.home, '.autoproj', 'gems')
58
+ @gems_install_path = default_gem_path
59
+ @autoproj_install_path = default_gem_path
53
60
  end
54
61
 
55
62
  def env_for_child
@@ -86,68 +93,91 @@ def self.in_workspace?(base_dir)
86
93
  return false
87
94
  end
88
95
 
89
-
96
+ # The path to the .autoproj configuration directory
97
+ #
98
+ # @return [String]
90
99
  def dot_autoproj; File.join(root_dir, '.autoproj') end
91
100
 
92
- def autoproj_install_dir; File.join(dot_autoproj, 'autoproj') end
93
101
  # The path to the gemfile used to install autoproj
94
- def autoproj_gemfile_path; File.join(autoproj_install_dir, 'Gemfile') end
95
- def autoproj_config_path; File.join(dot_autoproj, 'config.yml') end
102
+ #
103
+ # @return [String]
104
+ def autoproj_gemfile_path; File.join(dot_autoproj, 'Gemfile') end
96
105
 
97
- def shim_path; File.join(dot_autoproj, 'bin') end
106
+ # The path to the autoproj configuration file
107
+ #
108
+ # @return [String]
109
+ def autoproj_config_path; File.join(dot_autoproj, 'config.yml') end
98
110
 
99
111
  # Whether we can access the network while installing
100
112
  def local?; !!@local end
101
113
  # (see #local?)
102
114
  def local=(flag); @local = flag end
103
115
 
104
- # Whether bundler should be installed locally in {#dot_autoproj}
105
- def private_bundler?; !!@private_bundler end
106
- # The path to the directory into which the bundler gem should be
107
- # installed
108
- def bundler_gem_home; @private_bundler || Gem.user_dir end
109
- # (see #private_bundler?)
110
- def private_bundler=(flag)
111
- @private_bundler =
112
- if flag.respond_to?(:to_str) then File.expand_path(flag)
113
- elsif flag
114
- File.join(dot_autoproj, 'bundler')
115
- end
116
+ # The user-wide place where RubyGems installs gems
117
+ def dot_gem_dir
118
+ File.join(Gem.user_home, ".gem")
116
119
  end
117
120
 
118
- # Whether autoproj should be installed locally in {#dot_autoproj}
119
- def private_autoproj?; !!@private_autoproj end
120
- # The path to the directory into which the autoproj gem should be
121
- # installed
122
- def autoproj_gem_home; @private_autoproj || Gem.user_dir end
123
- # (see #private_autoproj?)
124
- def private_autoproj=(flag)
125
- @private_autoproj =
126
- if flag.respond_to?(:to_str) then File.expand_path(flag)
127
- elsif flag
128
- File.join(dot_autoproj, 'autoproj')
129
- end
121
+ # The version and platform-specific suffix under {#dot_gem_dir}
122
+ #
123
+ # This is also the suffix used by bundler to install gems
124
+ def gem_path_suffix
125
+ @gem_path_suffix ||= Pathname.new(Gem.user_dir).
126
+ relative_path_from(Pathname.new(dot_gem_dir)).to_s
130
127
  end
131
128
 
132
- # Whether autoproj should be installed locally in {#dot_autoproj}
129
+ # The path into which autoproj and its dependencies should be installed
133
130
  #
134
- # Unlike for {#private_autoproj?} and {#private_bundler?}, there is
135
- # no default path to save the gems as we don't yet know the path to
136
- # the prefix directory
137
- def private_gems?; !!@private_gems end
138
- # (see #private_gems?)
139
- def private_gems=(value)
140
- @private_gems =
141
- if value.respond_to?(:to_str) then File.expand_path(value)
142
- else value
143
- end
131
+ # They are installed in a versioned subdirectory of this path, e.g.
132
+ # {#gem_path_suffix}. It is always absolute.
133
+ #
134
+ # @return [String]
135
+ attr_reader :autoproj_install_path
136
+ # The GEM_HOME into which the autoproj gems should be installed
137
+ def autoproj_gem_home; File.join(autoproj_install_path, gem_path_suffix) end
138
+ # Sets the place where autoproj should be installed
139
+ #
140
+ # @param [String] path Sets the path given to bundler, i.e. the
141
+ # gems will be installed under the {#gem_path_suffix}
142
+ def autoproj_install_path=(path)
143
+ @autoproj_install_path = File.expand_path(path)
144
+ end
145
+ # Install autoproj in Gem's default user dir
146
+ def install_autoproj_in_gem_user_dir
147
+ @autoproj_install_path = File.join(Gem.user_home, '.gem')
148
+ end
149
+
150
+ # The path into which the workspace's gems should be installed
151
+ #
152
+ # They are installed in a versioned subdirectory of this path, e.g.
153
+ # {#gem_path_suffix}. Unlike {#autoproj_install_path}, it can be
154
+ # relative, in which case it is relative to the workspace's prefix
155
+ # directory.
156
+ #
157
+ # @return [String]
158
+ attr_reader :gems_install_path
159
+ # The GEM_HOME under which the workspace's gems should be installed
160
+ #
161
+ # @return [String]
162
+ def gems_gem_home; File.join(gems_install_path, gem_path_suffix) end
163
+ # Sets where the workspace's gems should be installed
164
+ #
165
+ # @param [String] path the absolute path that should be given to
166
+ # bundler. The gems themselves will be installed in the
167
+ # {#gem_path_suffix} subdirectory under this
168
+ def gems_install_path=(path)
169
+ @gems_install_path = path
170
+ end
171
+ # Install autoproj in Gem's default user dir
172
+ def install_gems_in_gem_user_dir
173
+ @gems_install_path = File.join(Gem.user_home, '.gem')
144
174
  end
145
175
 
146
176
  # Whether autoproj should prefer OS-independent packages over their
147
177
  # OS-packaged equivalents (e.g. the thor gem vs. the ruby-thor
148
178
  # Debian package)
149
179
  def prefer_indep_over_os_packages?; @prefer_indep_over_os_packages end
150
- # (see #private_gems?)
180
+ # (see #prefer_index_over_os_packages?)
151
181
  def prefer_indep_over_os_packages=(flag); @prefer_indep_over_os_packages = !!flag end
152
182
 
153
183
  def guess_gem_program
@@ -173,40 +203,32 @@ def guess_gem_program
173
203
  # that should be used
174
204
  # @return [String]
175
205
  def default_gemfile_contents(autoproj_version = ">= 2.0.0.a")
176
- ["source \"https://rubygems.org\"",
206
+ ["source \"#{gem_source}\"",
177
207
  "gem \"autoproj\", \"#{autoproj_version}\"",
178
208
  "gem \"utilrb\", \">= 3.0.0.a\""].join("\n")
179
209
  end
180
210
 
181
211
  # Parse the provided command line options and returns the non-options
182
212
  def parse_options(args = ARGV)
183
- default_gem_path = File.join(Dir.home, '.autoproj', 'gems')
184
- self.private_bundler = default_gem_path
185
- self.private_gems = default_gem_path
186
- self.private_autoproj = default_gem_path
187
-
188
213
  options = OptionParser.new do |opt|
189
214
  opt.on '--local', 'do not access the network (may fail)' do
190
215
  @local = true
191
216
  end
192
- opt.on '--public', "install gems in the default RubyGems locations. Consider using this if you don't have a v1 install anymore" do
193
- self.private_bundler = false
194
- self.private_autoproj = false
195
- self.private_gems = false
196
- end
197
- opt.on '--private-bundler[=PATH]', 'install bundler locally in the workspace, or in a dedicated path' do |path|
198
- self.private_bundler = path || true
217
+ opt.on '--gem-source=URL', String, "use this source for RubyGems instead of rubygems.org" do |url|
218
+ self.gem_source = url
199
219
  end
200
- opt.on '--private-autoproj[=PATH]', 'install autoproj locally in the workspace, or in a dedicated path' do |path|
201
- self.private_autoproj = path || true
202
- end
203
- opt.on '--private-gems[=PATH]', 'install gems locally in the prefix directory, or in a dedicated path' do |path|
204
- self.private_gems = path || true
220
+ opt.on '--shared-gems[=PATH]', "install gems in a shared location. By default, uses the default RubyGems locations" do |path|
221
+ if path
222
+ self.autoproj_install_path = path
223
+ self.gems_install_path = path
224
+ else
225
+ self.install_autoproj_in_gem_user_dir
226
+ self.install_gems_in_gem_user_dir
227
+ end
205
228
  end
206
- opt.on '--private[=PATH]', "whether bundler, autoproj and the workspace gems should be installed locally in the workspace. This is the default, with a path of #{default_gem_path}" do |path|
207
- self.private_bundler = path || true
208
- self.private_autoproj = path || true
209
- self.private_gems = path || true
229
+ opt.on '--private-gems', "install bundler, autoproj and the workspace gems in dedicated locations within the workspace" do |path|
230
+ self.autoproj_install_path = File.join(dot_autoproj, 'gems')
231
+ self.gems_install_path = 'gems'
210
232
  end
211
233
  opt.on '--version=VERSION_CONSTRAINT', String, 'use the provided string as a version constraint for autoproj' do |version|
212
234
  @gemfile = default_gemfile_contents(version)
@@ -237,12 +259,12 @@ def parse_options(args = ARGV)
237
259
 
238
260
  def find_bundler(gem_program)
239
261
  result = system(
240
- env_for_child.merge('GEM_PATH' => "", 'GEM_HOME' => bundler_gem_home),
262
+ env_for_child,
241
263
  Gem.ruby, gem_program, 'which', 'bundler/setup',
242
264
  out: '/dev/null')
243
265
  return if !result
244
266
 
245
- bundler_path = File.join(bundler_gem_home, 'bin', 'bundler')
267
+ bundler_path = File.join(autoproj_gem_home, 'bin', 'bundler')
246
268
  if File.exist?(bundler_path)
247
269
  bundler_path
248
270
  end
@@ -252,17 +274,17 @@ def install_bundler(gem_program)
252
274
  local = ['--local'] if local?
253
275
 
254
276
  result = system(
255
- env_for_child.merge('GEM_PATH' => "", 'GEM_HOME' => bundler_gem_home),
256
- Gem.ruby, gem_program, 'install', '--env-shebang', '--no-document', '--no-format-executable',
277
+ env_for_child,
278
+ Gem.ruby, gem_program, 'install', '--env-shebang', '--no-document', '--no-format-executable', '--clear-sources', '--source', gem_source,
257
279
  *local,
258
- "--bindir=#{File.join(bundler_gem_home, 'bin')}", 'bundler')
280
+ "--bindir=#{File.join(autoproj_gem_home, 'bin')}", 'bundler')
259
281
 
260
282
  if !result
261
- STDERR.puts "FATAL: failed to install bundler in #{bundler_gem_home}"
283
+ STDERR.puts "FATAL: failed to install bundler in #{autoproj_gem_home}"
262
284
  nil
263
285
  end
264
286
 
265
- bundler_path = File.join(bundler_gem_home, 'bin', 'bundler')
287
+ bundler_path = File.join(autoproj_gem_home, 'bin', 'bundler')
266
288
  if File.exist?(bundler_path)
267
289
  bundler_path
268
290
  else
@@ -274,7 +296,7 @@ def install_bundler(gem_program)
274
296
  def install_autoproj(bundler)
275
297
  # Force bundler to update. If the user does not want this, let him specify a
276
298
  # Gemfile with tighter version constraints
277
- lockfile = File.join(autoproj_install_dir, 'Gemfile.lock')
299
+ lockfile = File.join(dot_autoproj, 'Gemfile.lock')
278
300
  if File.exist?(lockfile)
279
301
  FileUtils.rm lockfile
280
302
  end
@@ -283,30 +305,26 @@ def install_autoproj(bundler)
283
305
 
284
306
  opts = Array.new
285
307
  opts << '--local' if local?
286
- if private_autoproj?
287
- clean_env['GEM_PATH'] = bundler_gem_home
288
- clean_env['GEM_HOME'] = nil
289
- opts << "--path=#{autoproj_gem_home}"
290
- end
291
- binstubs_path = File.join(autoproj_install_dir, 'bin')
292
- result = system(clean_env.merge('GEM_HOME' => autoproj_gem_home),
308
+ opts << "--path=#{autoproj_install_path}"
309
+ shims_path = File.join(dot_autoproj, 'bin')
310
+ result = system(clean_env,
293
311
  Gem.ruby, bundler, 'install',
294
312
  "--gemfile=#{autoproj_gemfile_path}",
295
313
  "--shebang=#{Gem.ruby}",
296
- "--binstubs=#{binstubs_path}",
297
- *opts, chdir: autoproj_install_dir)
314
+ "--binstubs=#{shims_path}",
315
+ *opts, chdir: dot_autoproj)
298
316
 
299
317
  if !result
300
318
  STDERR.puts "FATAL: failed to install autoproj in #{dot_autoproj}"
301
319
  exit 1
302
320
  end
303
321
  ensure
304
- self.class.clean_binstubs(binstubs_path)
322
+ self.class.clean_binstubs(shims_path, ruby_executable, bundler)
305
323
  end
306
324
 
307
- def self.clean_binstubs(binstubs_path)
308
- %w{bundler bundle rake thor}.each do |bundler_bin|
309
- path = File.join(binstubs_path, bundler_bin)
325
+ def self.clean_binstubs(shim_path, ruby_executable, bundler_path)
326
+ %w{bundler bundle rake thor ruby}.each do |bundler_bin|
327
+ path = File.join(shim_path, bundler_bin)
310
328
  if File.file?(path)
311
329
  FileUtils.rm path
312
330
  end
@@ -315,7 +333,7 @@ def self.clean_binstubs(binstubs_path)
315
333
  # Now tune the binstubs to force the usage of the autoproj
316
334
  # gemfile. Otherwise, they get BUNDLE_GEMFILE from the
317
335
  # environment by default
318
- Dir.glob(File.join(binstubs_path, '*')) do |path|
336
+ Dir.glob(File.join(shim_path, '*')) do |path|
319
337
  next if !File.file?(path)
320
338
 
321
339
  lines = File.readlines(path)
@@ -331,6 +349,9 @@ def self.clean_binstubs(binstubs_path)
331
349
  io.write filtered.join("")
332
350
  end
333
351
  end
352
+
353
+ ensure
354
+ save_ruby_and_bundler_shims(shim_path, ruby_executable, bundler_path)
334
355
  end
335
356
 
336
357
  def save_env_sh(*vars)
@@ -403,8 +424,9 @@ def gem_bindir
403
424
  end
404
425
  end
405
426
 
406
- def save_ruby_and_bundler_shims(bundler_path)
427
+ def self.save_ruby_and_bundler_shims(shim_path, ruby_executable, bundler_path)
407
428
  FileUtils.mkdir_p shim_path
429
+ bundler_rubylib = File.expand_path(File.join('..', '..', 'lib'), bundler_path)
408
430
  File.open(File.join(shim_path, 'bundler'), 'w') do |io|
409
431
  io.puts "#! /bin/sh"
410
432
  io.puts "exec #{ruby_executable} #{bundler_path} \"$@\""
@@ -424,25 +446,25 @@ def install
424
446
 
425
447
  gem_program = guess_gem_program
426
448
  puts "Detected 'gem' to be #{gem_program}"
449
+ env['GEM_HOME'] = [autoproj_gem_home]
427
450
 
428
451
  if bundler = find_bundler(gem_program)
429
452
  puts "Detected bundler at #{bundler}"
430
453
  else
431
- puts "Installing bundler in #{bundler_gem_home}"
454
+ puts "Installing bundler in #{autoproj_gem_home}"
432
455
  if !(bundler = install_bundler(gem_program))
433
456
  exit 1
434
457
  end
435
- if private_bundler?
436
- env['GEM_PATH'].unshift bundler_gem_home
437
- end
438
458
  end
439
- save_ruby_and_bundler_shims(bundler)
440
- env['PATH'].unshift shim_path
459
+ self.class.save_ruby_and_bundler_shims(
460
+ File.join(dot_autoproj, 'bin'),
461
+ ruby_executable,
462
+ bundler)
463
+ env['PATH'].unshift File.join(dot_autoproj, 'bin')
441
464
  save_gemfile
442
465
 
443
- puts "Installing autoproj#{" in #{autoproj_gem_home}" if private_autoproj?}"
466
+ puts "Installing autoproj in #{autoproj_gem_home}"
444
467
  install_autoproj(bundler)
445
- env['PATH'].unshift File.join(dot_autoproj, 'autoproj', 'bin')
446
468
  end
447
469
 
448
470
  def load_config
@@ -468,21 +490,20 @@ def load_config
468
490
  end
469
491
 
470
492
  @config = config
471
- %w{private_bundler private_gems private_autoproj prefer_indep_over_os_packages}.each do |flag|
493
+ %w{autoproj_install_path gems_install_path prefer_indep_over_os_packages}.each do |flag|
472
494
  instance_variable_set "@#{flag}", config.fetch(flag, false)
473
495
  end
474
496
  end
475
497
 
476
498
  def save_config
477
- config['private_bundler'] = (bundler_gem_home if private_bundler?)
478
- config['private_autoproj'] = (autoproj_gem_home if private_autoproj?)
479
- config['private_gems'] = @private_gems
499
+ config['autoproj_install_path'] = autoproj_install_path
500
+ config['gems_install_path'] = gems_install_path
480
501
  config['prefer_indep_over_os_packages'] = prefer_indep_over_os_packages?
481
502
  File.open(autoproj_config_path, 'w') { |io| YAML.dump(config, io) }
482
503
  end
483
504
 
484
505
  def autoproj_path
485
- File.join(autoproj_install_dir, 'bin', 'autoproj')
506
+ File.join(dot_autoproj, 'bin', 'autoproj')
486
507
  end
487
508
 
488
509
  def run_autoproj(*args)
@@ -521,11 +542,13 @@ def stage2(*vars)
521
542
  puts "saving env.sh and .autoproj/env.sh"
522
543
  save_env_sh(*vars)
523
544
  if !system(Gem.ruby, autoproj_path, 'envsh', *autoproj_options)
545
+ STDERR.puts "failed to run autoproj envsh on the newly installed autoproj (#{autoproj_path})"
524
546
  exit 1
525
547
  end
526
548
  # This is really needed on an existing install to install the
527
549
  # gems that were present in the v1 layout
528
550
  if !system(Gem.ruby, autoproj_path, 'osdeps')
551
+ STDERR.puts "failed to run autoproj osdeps on the newly installed autoproj (#{autoproj_path})"
529
552
  exit 1
530
553
  end
531
554
  end