autoproj 2.0.0.rc4 → 2.0.0.rc5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bbe30e7cd487de7bf07f9cf6b19d1766caa87aa4
4
- data.tar.gz: e88e2b24c5e121542212cb253296b7c73fa01681
3
+ metadata.gz: df06bafc27ce59e3c5ad6c46590c44045755f496
4
+ data.tar.gz: 340b8871ba997370ed1b8b6fc526a7388c30de18
5
5
  SHA512:
6
- metadata.gz: bfdabcb92034ade239d6e7df0438b5e4e77b1cf3ad88a1b05d1cdc3e3b265ec351523511b9ca89e878d898928ae64e287d7f3486394e29fcc1e1da77687f3dd6
7
- data.tar.gz: 07506f2a88a2f999b91faa521475bfd203ae24a6f5587f00f3bd1fc49c60865807501f4b205f91bf0cc7abd6840ed58813810d23500b5e5f69d65cbded0b76ef
6
+ metadata.gz: 44b11ccb7dacb6e6dac7f3fad212c5755e5fd00fb2416ef303744333b7c26afa09894af22a755a3ef69dbdc04a4d05f87a556e104ebb87e7fc35c8e67cac1e3b
7
+ data.tar.gz: e65540e5a2a77faf9e10e0a425e5f723ae25737f76575ed0e31b2050e66e6072c2210c0431f90da82e9fa237ef642b5e153c45ff3e62afe032a00afb0960c71f
data/.travis.yml CHANGED
@@ -1,5 +1,9 @@
1
+ sudo: false
1
2
  language: ruby
2
3
  rvm:
3
4
  - 2.0.0
4
5
  - 2.1.6
5
6
  - 2.2.2
7
+ script:
8
+ - bundler exec rake
9
+ - bundler exec rake test
data/bin/alocate CHANGED
@@ -1,6 +1,6 @@
1
1
  #! /usr/bin/env ruby
2
2
 
3
- require 'autoproj/cli/locate'
3
+ require 'autoproj/cli/main'
4
4
  Autoproj::CLI.basic_setup
5
5
  Autoproj::CLI::Main.start(['locate', *ARGV])
6
6
 
data/bin/autoproj CHANGED
@@ -1,11 +1,12 @@
1
1
  #! /usr/bin/env ruby
2
2
 
3
- require 'autoproj'
4
- require 'autoproj/autobuild'
5
3
  require 'autoproj/cli'
6
4
  require 'autoproj/cli/main'
7
5
  Autoproj::CLI.basic_setup
8
6
 
9
- Autoproj::CLI.load_plugins
10
- Autoproj::CLI::Main.start(ARGV)
7
+ argv = ARGV.find_all { |arg| arg != "--no-plugins" }
8
+ if argv.size == ARGV.size
9
+ Autoproj::CLI.load_plugins
10
+ end
11
+ Autoproj::CLI::Main.start(argv)
11
12
 
@@ -5,6 +5,7 @@ if RUBY_VERSION < "1.9.2"
5
5
  exit 1
6
6
  end
7
7
 
8
+ require 'pathname'
8
9
  require 'optparse'
9
10
  require 'fileutils'
10
11
  require 'yaml'
@@ -17,19 +18,65 @@ module Autoproj
17
18
  # It can be required standalone (i.e. does not depend on anything else than
18
19
  # ruby and the ruby standard library)
19
20
  class Install
21
+ class UnexpectedBinstub < RuntimeError; end
22
+
20
23
  # The directory in which to install autoproj
21
24
  attr_reader :root_dir
22
25
  # Content of the Gemfile generated to install autoproj itself
23
26
  attr_accessor :gemfile
27
+ # The environment that is passed to the bundler installs
28
+ attr_reader :env
24
29
 
25
30
  def initialize(root_dir)
26
31
  @root_dir = root_dir
27
- @gemfile = default_gemfile_contents
32
+ if File.file?(autoproj_gemfile_path)
33
+ @gemfile = File.read(autoproj_gemfile_path)
34
+ else
35
+ @gemfile = default_gemfile_contents
36
+ end
37
+
28
38
  @private_bundler = false
29
39
  @private_autoproj = false
30
40
  @private_gems = false
41
+ @local = false
42
+ @env = self.class.clean_env
43
+ end
44
+
45
+ def self.clean_env
46
+ env = Hash.new
47
+ env['RUBYLIB'] = []
48
+ env['GEM_PATH'] = []
49
+ %w{PATH GEM_HOME}.each do |name|
50
+ env[name] = sanitize_env(ENV[name] || "")
51
+ end
52
+ env['BUNDLE_GEMFILE'] = nil
53
+ env
54
+ end
55
+
56
+ def env_for_child
57
+ env.inject(Hash.new) do |h, (k, v)|
58
+ h[k] = (v.join(File::PATH_SEPARATOR) if v && !v.empty?)
59
+ h
60
+ end
61
+ end
62
+
63
+ def self.sanitize_env(value)
64
+ value.split(File::PATH_SEPARATOR).
65
+ find_all { |p| !in_workspace?(p) }
66
+ end
67
+
68
+ def self.in_workspace?(base_dir)
69
+ path = Pathname.new(base_dir)
70
+ while !path.root?
71
+ if (path + ".autoproj").exist? || (path + "autoproj").exist?
72
+ return true
73
+ end
74
+ path = path.parent
75
+ end
76
+ return false
31
77
  end
32
78
 
79
+
33
80
  def dot_autoproj; File.join(root_dir, '.autoproj') end
34
81
  def bin_dir; File.join(dot_autoproj, 'bin') end
35
82
  def bundler_install_dir; File.join(dot_autoproj, 'bundler') end
@@ -38,13 +85,24 @@ module Autoproj
38
85
  def autoproj_gemfile_path; File.join(autoproj_install_dir, 'Gemfile') end
39
86
  def autoproj_config_path; File.join(dot_autoproj, 'config.yml') end
40
87
 
88
+ # Whether we can access the network while installing
89
+ def local?; !!@local end
90
+ # (see #local?)
91
+ def local=(flag); @local = flag end
92
+
41
93
  # Whether bundler should be installed locally in {#dot_autoproj}
42
94
  def private_bundler?; @private_bundler end
95
+ # (see #private_bundler?)
96
+ def private_bundler=(flag); @private_bundler = flag end
43
97
  # Whether autoproj should be installed locally in {#dot_autoproj}
44
98
  def private_autoproj?; @private_autoproj end
99
+ # (see #private_autoproj?)
100
+ def private_autoproj=(flag); @private_autoproj = flag end
45
101
  # Whether bundler should be installed locally in the workspace
46
102
  # prefix directory
47
103
  def private_gems?; @private_gems end
104
+ # (see #private_gems?)
105
+ def private_gems=(flag); @private_gems = flag end
48
106
 
49
107
  def guess_gem_program
50
108
  ruby_bin = RbConfig::CONFIG['RUBY_INSTALL_NAME']
@@ -68,14 +126,18 @@ module Autoproj
68
126
  # @param [String] autoproj_version a constraint on the autoproj version
69
127
  # that should be used
70
128
  # @return [String]
71
- def default_gemfile_contents(autoproj_version = ">= 0")
129
+ def default_gemfile_contents(autoproj_version = ">= 2.0.0.a")
72
130
  ["source \"https://rubygems.org\"",
73
- "gem \"autoproj\", \"#{autoproj_version}\""].join("\n")
131
+ "gem \"autoproj\", \"#{autoproj_version}\"",
132
+ "gem \"utilrb\", \">= 3.0.0.a\""].join("\n")
74
133
  end
75
134
 
76
135
  # Parse the provided command line options and returns the non-options
77
136
  def parse_options(args = ARGV)
78
137
  options = OptionParser.new do |opt|
138
+ opt.on '--local', 'do not access the network (may fail)' do
139
+ @local = true
140
+ end
79
141
  opt.on '--private-bundler', 'install bundler locally in the workspace' do
80
142
  @private_bundler = true
81
143
  end
@@ -104,28 +166,37 @@ module Autoproj
104
166
  gem_program = guess_gem_program
105
167
  puts "Detected 'gem' to be #{gem_program}"
106
168
 
169
+ local = ['--local'] if local?
170
+
107
171
  result = system(
108
- Hash['GEM_PATH' => nil,
109
- 'GEM_HOME' => bundler_install_dir],
172
+ env_for_child.merge('GEM_PATH' => nil, 'GEM_HOME' => bundler_install_dir),
110
173
  gem_program, 'install', '--no-document', '--no-user-install', '--no-format-executable',
174
+ *local,
111
175
  "--bindir=#{File.join(bundler_install_dir, 'bin')}", 'bundler')
112
176
 
113
177
  if !result
114
178
  STDERR.puts "FATAL: failed to install bundler in #{dot_autoproj}"
115
179
  exit 1
116
180
  end
181
+ env['GEM_PATH'] << bundler_install_dir
182
+ env['PATH'] << File.join(bundler_install_dir, 'bin')
117
183
  File.join(bin_dir, 'bundler')
118
184
  end
119
185
 
120
186
  def save_env_sh
121
187
  env = Autobuild::Environment.new
122
- path = []
123
- if private_bundler?
124
- env.push_path 'PATH', File.join(bundler_install_dir, 'bin')
125
- env.push_path 'GEM_PATH', bundler_install_dir
188
+ env.prepare
189
+
190
+ %w{GEM_HOME GEM_PATH}.each do |name|
191
+ value = self.env[name]
192
+ if value.empty?
193
+ env.unset name
194
+ else
195
+ env.set name, *value
196
+ end
126
197
  end
127
198
  env.push_path 'PATH', File.join(autoproj_install_dir, 'bin')
128
- env.inherit 'PATH'
199
+
129
200
  if private_autoproj?
130
201
  env.push_path 'GEM_PATH', autoproj_install_dir
131
202
  end
@@ -149,7 +220,9 @@ export AUTOPROJ_CURRENT_ROOT=#{root_dir}
149
220
  io.write gemfile
150
221
  end
151
222
  end
152
-
223
+
224
+ ENV_BUNDLE_GEMFILE_RX = /^(\s*ENV\[['"]BUNDLE_GEMFILE['"]\]\s*)(?:\|\|)?=/
225
+
153
226
  def install_autoproj(bundler)
154
227
  # Force bundler to update. If the user does not want this, let him specify a
155
228
  # Gemfile with tighter version constraints
@@ -158,24 +231,57 @@ export AUTOPROJ_CURRENT_ROOT=#{root_dir}
158
231
  FileUtils.rm lockfile
159
232
  end
160
233
 
161
- env = Hash['BUNDLE_GEMFILE' => nil, 'RUBYLIB' => nil]
162
234
  opts = Array.new
235
+ opts << '--local' if local?
163
236
 
237
+ env = env_for_child
164
238
  if private_autoproj?
165
- env = Hash['GEM_PATH' => bundler_install_dir,
166
- 'GEM_HOME' => nil]
239
+ env = env.merge(
240
+ 'GEM_PATH' => bundler_install_dir,
241
+ 'GEM_HOME' => nil)
167
242
  opts << "--clean" << "--path=#{autoproj_install_dir}"
168
243
  end
169
244
 
245
+ binstubs_path = File.join(autoproj_install_dir, 'bin')
246
+
170
247
  result = system(env,
171
- bundler, 'install',
248
+ Gem.ruby, bundler, 'install',
172
249
  "--gemfile=#{autoproj_gemfile_path}",
173
- "--binstubs=#{File.join(autoproj_install_dir, 'bin')}",
250
+ "--binstubs=#{binstubs_path}",
174
251
  *opts)
175
252
  if !result
176
253
  STDERR.puts "FATAL: failed to install autoproj in #{dot_autoproj}"
177
254
  exit 1
178
255
  end
256
+
257
+ # Now tune the binstubs to force the usage of the autoproj
258
+ # gemfile. Otherwise, they get BUNDLE_GEMFILE from the
259
+ # environment by default
260
+ Dir.glob(File.join(binstubs_path, '*')) do |path|
261
+ next if !File.file?(path)
262
+ # Do NOT do that for bundler, otherwise it will fail with an
263
+ # "already loaded gemfile" message once we e.g. try to do
264
+ # 'bundler install --gemfile=NEW_GEMFILE'
265
+ next if File.basename(path) == 'bundler'
266
+
267
+ lines = File.readlines(path)
268
+ matched = false
269
+ filtered = lines.map do |l|
270
+ matched ||= (ENV_BUNDLE_GEMFILE_RX === l)
271
+ l.gsub(ENV_BUNDLE_GEMFILE_RX, '\\1=')
272
+ end
273
+ if !matched
274
+ raise UnexpectedBinstub, "expected #{path} to contain a line looking like ENV['BUNDLE_GEMFILE'] ||= but could not find one"
275
+ end
276
+ File.open(path, 'w') do |io|
277
+ io.write filtered.join("")
278
+ end
279
+ end
280
+
281
+ env['PATH'] << File.join(autoproj_install_dir, 'bin')
282
+ if private_autoproj?
283
+ env['GEM_PATH'] << autoproj_install_dir
284
+ end
179
285
  end
180
286
 
181
287
  def update_configuration
@@ -192,25 +298,92 @@ export AUTOPROJ_CURRENT_ROOT=#{root_dir}
192
298
  end
193
299
  end
194
300
 
301
+ def find_in_clean_path(command)
302
+ clean_path = env_for_child['PATH'].split(File::PATH_SEPARATOR)
303
+ clean_path.each do |p|
304
+ full_path = File.join(p, command)
305
+ if File.file?(full_path)
306
+ return full_path
307
+ end
308
+ end
309
+ nil
310
+ end
311
+
312
+ def find_bundler
313
+ clean_env = env_for_child
314
+ Gem.paths = Hash[
315
+ 'GEM_HOME' => clean_env['GEM_HOME'] || Gem.default_dir,
316
+ 'GEM_PATH' => clean_env['GEM_PATH'] || nil
317
+ ]
318
+ # Here, we're getting into the esotheric
319
+ #
320
+ # The problem is that e.g. Ubuntu and Debian install an
321
+ # operating_system.rb file that sets proper OS defaults. Some
322
+ # autoproj installs have it in their RUBYLIB but should not
323
+ # because of limitations of autoproj 1.x. This leads to
324
+ # Gem.bindir being *not* valid for subprocesses
325
+ #
326
+ # So, we're calling 'gem' as a subcommand to discovery the
327
+ # actual bindir
328
+ bindir = IO.popen(clean_env, [Gem.ruby, '-e', 'puts Gem.bindir']).read
329
+ if bindir
330
+ env['PATH'].unshift bindir.chomp
331
+ else
332
+ STDERR.puts "FATAL: cannot run #{Gem.ruby} -e 'puts Gem.bindir'"
333
+ exit 1
334
+ end
335
+
336
+ bundler = find_in_clean_path('bundler')
337
+ if !bundler
338
+ clean_path = env_for_child['PATH']
339
+ STDERR.puts "FATAL: cannot find 'bundler' in PATH=#{clean_path}"
340
+ if ENV['PATH'] != clean_path
341
+ STDERR.puts " it appears that you already have some autoproj-generated env.sh loaded"
342
+ STDERR.puts " - if you are running 'autoproj upgrade', please contact the autoproj author at https://github.com/rock-core/autoproj/issues/new"
343
+ STDERR.puts " - if you are running an install, try again in a console where the env.sh is not loaded"
344
+ exit 1
345
+ else
346
+ STDERR.puts " the recommended action is to install it manually first by running 'gem install bundler'"
347
+ STDERR.puts " or call this command again with --private-bundler to have it installed in the workspace"
348
+ exit 1
349
+ end
350
+ end
351
+ bundler
352
+ end
353
+
195
354
  def install
196
355
  if private_bundler?
197
356
  puts "Installing bundler in #{bundler_install_dir}"
198
357
  bundler = install_bundler
358
+ else
359
+ bundler = find_bundler
360
+ puts "Detected bundler at #{bundler}"
199
361
  end
200
362
  save_gemfile
201
363
  puts "Installing autoproj in #{dot_autoproj}"
202
- install_autoproj(bundler || 'bundler')
364
+ install_autoproj(bundler)
203
365
  end
204
366
 
205
367
  # Actually perform the install
206
- def run
207
- install
208
- ENV['BUNDLE_GEMFILE'] = autoproj_gemfile_path
209
- require 'bundler'
210
- Bundler.setup
211
- require 'autobuild'
212
- save_env_sh
213
- update_configuration
368
+ def run(stage2: false)
369
+ if stage2
370
+ require 'autobuild'
371
+ save_env_sh
372
+ else
373
+ install
374
+
375
+ env_for_child.each do |k, v|
376
+ if v
377
+ ENV[k] = v
378
+ else
379
+ ENV.delete(k)
380
+ end
381
+ end
382
+ ENV['BUNDLE_GEMFILE'] = autoproj_gemfile_path
383
+ update_configuration
384
+ exec Gem.ruby, File.join(autoproj_install_dir, 'bin', 'autoproj'),
385
+ 'install-stage2', root_dir
386
+ end
214
387
  end
215
388
  end
216
389
  end
@@ -219,5 +392,11 @@ end
219
392
 
220
393
 
221
394
  ops = Autoproj::Ops::Install.new(Dir.pwd)
222
- ops.parse_options(ARGV)
395
+ bootstrap_options = ops.parse_options(ARGV)
223
396
  ops.run
397
+
398
+ # we assume that Install#run loads bundler and autobuild. Load autoproj and run
399
+ # bootstrap
400
+ require 'autoproj/cli/main'
401
+ Autoproj::CLI::Main.start(['bootstrap', *bootstrap_options])
402
+
@@ -8,5 +8,11 @@ end
8
8
  AUTOPROJ_OPS_INSTALL
9
9
 
10
10
  ops = Autoproj::Ops::Install.new(Dir.pwd)
11
- ops.parse_options(ARGV)
11
+ bootstrap_options = ops.parse_options(ARGV)
12
12
  ops.run
13
+
14
+ # we assume that Install#run loads bundler and autobuild. Load autoproj and run
15
+ # bootstrap
16
+ require 'autoproj/cli/main'
17
+ Autoproj::CLI::Main.start(['bootstrap', *bootstrap_options])
18
+
data/bin/autoproj_install CHANGED
@@ -5,6 +5,7 @@ if RUBY_VERSION < "1.9.2"
5
5
  exit 1
6
6
  end
7
7
 
8
+ require 'pathname'
8
9
  require 'optparse'
9
10
  require 'fileutils'
10
11
  require 'yaml'
@@ -17,19 +18,65 @@ module Autoproj
17
18
  # It can be required standalone (i.e. does not depend on anything else than
18
19
  # ruby and the ruby standard library)
19
20
  class Install
21
+ class UnexpectedBinstub < RuntimeError; end
22
+
20
23
  # The directory in which to install autoproj
21
24
  attr_reader :root_dir
22
25
  # Content of the Gemfile generated to install autoproj itself
23
26
  attr_accessor :gemfile
27
+ # The environment that is passed to the bundler installs
28
+ attr_reader :env
24
29
 
25
30
  def initialize(root_dir)
26
31
  @root_dir = root_dir
27
- @gemfile = default_gemfile_contents
32
+ if File.file?(autoproj_gemfile_path)
33
+ @gemfile = File.read(autoproj_gemfile_path)
34
+ else
35
+ @gemfile = default_gemfile_contents
36
+ end
37
+
28
38
  @private_bundler = false
29
39
  @private_autoproj = false
30
40
  @private_gems = false
41
+ @local = false
42
+ @env = self.class.clean_env
43
+ end
44
+
45
+ def self.clean_env
46
+ env = Hash.new
47
+ env['RUBYLIB'] = []
48
+ env['GEM_PATH'] = []
49
+ %w{PATH GEM_HOME}.each do |name|
50
+ env[name] = sanitize_env(ENV[name] || "")
51
+ end
52
+ env['BUNDLE_GEMFILE'] = nil
53
+ env
31
54
  end
32
55
 
56
+ def env_for_child
57
+ env.inject(Hash.new) do |h, (k, v)|
58
+ h[k] = (v.join(File::PATH_SEPARATOR) if v && !v.empty?)
59
+ h
60
+ end
61
+ end
62
+
63
+ def self.sanitize_env(value)
64
+ value.split(File::PATH_SEPARATOR).
65
+ find_all { |p| !in_workspace?(p) }
66
+ end
67
+
68
+ def self.in_workspace?(base_dir)
69
+ path = Pathname.new(base_dir)
70
+ while !path.root?
71
+ if (path + ".autoproj").exist? || (path + "autoproj").exist?
72
+ return true
73
+ end
74
+ path = path.parent
75
+ end
76
+ return false
77
+ end
78
+
79
+
33
80
  def dot_autoproj; File.join(root_dir, '.autoproj') end
34
81
  def bin_dir; File.join(dot_autoproj, 'bin') end
35
82
  def bundler_install_dir; File.join(dot_autoproj, 'bundler') end
@@ -38,13 +85,24 @@ module Autoproj
38
85
  def autoproj_gemfile_path; File.join(autoproj_install_dir, 'Gemfile') end
39
86
  def autoproj_config_path; File.join(dot_autoproj, 'config.yml') end
40
87
 
88
+ # Whether we can access the network while installing
89
+ def local?; !!@local end
90
+ # (see #local?)
91
+ def local=(flag); @local = flag end
92
+
41
93
  # Whether bundler should be installed locally in {#dot_autoproj}
42
94
  def private_bundler?; @private_bundler end
95
+ # (see #private_bundler?)
96
+ def private_bundler=(flag); @private_bundler = flag end
43
97
  # Whether autoproj should be installed locally in {#dot_autoproj}
44
98
  def private_autoproj?; @private_autoproj end
99
+ # (see #private_autoproj?)
100
+ def private_autoproj=(flag); @private_autoproj = flag end
45
101
  # Whether bundler should be installed locally in the workspace
46
102
  # prefix directory
47
103
  def private_gems?; @private_gems end
104
+ # (see #private_gems?)
105
+ def private_gems=(flag); @private_gems = flag end
48
106
 
49
107
  def guess_gem_program
50
108
  ruby_bin = RbConfig::CONFIG['RUBY_INSTALL_NAME']
@@ -68,14 +126,18 @@ module Autoproj
68
126
  # @param [String] autoproj_version a constraint on the autoproj version
69
127
  # that should be used
70
128
  # @return [String]
71
- def default_gemfile_contents(autoproj_version = ">= 0")
129
+ def default_gemfile_contents(autoproj_version = ">= 2.0.0.a")
72
130
  ["source \"https://rubygems.org\"",
73
- "gem \"autoproj\", \"#{autoproj_version}\""].join("\n")
131
+ "gem \"autoproj\", \"#{autoproj_version}\"",
132
+ "gem \"utilrb\", \">= 3.0.0.a\""].join("\n")
74
133
  end
75
134
 
76
135
  # Parse the provided command line options and returns the non-options
77
136
  def parse_options(args = ARGV)
78
137
  options = OptionParser.new do |opt|
138
+ opt.on '--local', 'do not access the network (may fail)' do
139
+ @local = true
140
+ end
79
141
  opt.on '--private-bundler', 'install bundler locally in the workspace' do
80
142
  @private_bundler = true
81
143
  end
@@ -104,28 +166,37 @@ module Autoproj
104
166
  gem_program = guess_gem_program
105
167
  puts "Detected 'gem' to be #{gem_program}"
106
168
 
169
+ local = ['--local'] if local?
170
+
107
171
  result = system(
108
- Hash['GEM_PATH' => nil,
109
- 'GEM_HOME' => bundler_install_dir],
172
+ env_for_child.merge('GEM_PATH' => nil, 'GEM_HOME' => bundler_install_dir),
110
173
  gem_program, 'install', '--no-document', '--no-user-install', '--no-format-executable',
174
+ *local,
111
175
  "--bindir=#{File.join(bundler_install_dir, 'bin')}", 'bundler')
112
176
 
113
177
  if !result
114
178
  STDERR.puts "FATAL: failed to install bundler in #{dot_autoproj}"
115
179
  exit 1
116
180
  end
181
+ env['GEM_PATH'] << bundler_install_dir
182
+ env['PATH'] << File.join(bundler_install_dir, 'bin')
117
183
  File.join(bin_dir, 'bundler')
118
184
  end
119
185
 
120
186
  def save_env_sh
121
187
  env = Autobuild::Environment.new
122
- path = []
123
- if private_bundler?
124
- env.push_path 'PATH', File.join(bundler_install_dir, 'bin')
125
- env.push_path 'GEM_PATH', bundler_install_dir
188
+ env.prepare
189
+
190
+ %w{GEM_HOME GEM_PATH}.each do |name|
191
+ value = self.env[name]
192
+ if value.empty?
193
+ env.unset name
194
+ else
195
+ env.set name, *value
196
+ end
126
197
  end
127
198
  env.push_path 'PATH', File.join(autoproj_install_dir, 'bin')
128
- env.inherit 'PATH'
199
+
129
200
  if private_autoproj?
130
201
  env.push_path 'GEM_PATH', autoproj_install_dir
131
202
  end
@@ -149,7 +220,9 @@ export AUTOPROJ_CURRENT_ROOT=#{root_dir}
149
220
  io.write gemfile
150
221
  end
151
222
  end
152
-
223
+
224
+ ENV_BUNDLE_GEMFILE_RX = /^(\s*ENV\[['"]BUNDLE_GEMFILE['"]\]\s*)(?:\|\|)?=/
225
+
153
226
  def install_autoproj(bundler)
154
227
  # Force bundler to update. If the user does not want this, let him specify a
155
228
  # Gemfile with tighter version constraints
@@ -158,24 +231,57 @@ export AUTOPROJ_CURRENT_ROOT=#{root_dir}
158
231
  FileUtils.rm lockfile
159
232
  end
160
233
 
161
- env = Hash['BUNDLE_GEMFILE' => nil, 'RUBYLIB' => nil]
162
234
  opts = Array.new
235
+ opts << '--local' if local?
163
236
 
237
+ env = env_for_child
164
238
  if private_autoproj?
165
- env = Hash['GEM_PATH' => bundler_install_dir,
166
- 'GEM_HOME' => nil]
239
+ env = env.merge(
240
+ 'GEM_PATH' => bundler_install_dir,
241
+ 'GEM_HOME' => nil)
167
242
  opts << "--clean" << "--path=#{autoproj_install_dir}"
168
243
  end
169
244
 
245
+ binstubs_path = File.join(autoproj_install_dir, 'bin')
246
+
170
247
  result = system(env,
171
- bundler, 'install',
248
+ Gem.ruby, bundler, 'install',
172
249
  "--gemfile=#{autoproj_gemfile_path}",
173
- "--binstubs=#{File.join(autoproj_install_dir, 'bin')}",
250
+ "--binstubs=#{binstubs_path}",
174
251
  *opts)
175
252
  if !result
176
253
  STDERR.puts "FATAL: failed to install autoproj in #{dot_autoproj}"
177
254
  exit 1
178
255
  end
256
+
257
+ # Now tune the binstubs to force the usage of the autoproj
258
+ # gemfile. Otherwise, they get BUNDLE_GEMFILE from the
259
+ # environment by default
260
+ Dir.glob(File.join(binstubs_path, '*')) do |path|
261
+ next if !File.file?(path)
262
+ # Do NOT do that for bundler, otherwise it will fail with an
263
+ # "already loaded gemfile" message once we e.g. try to do
264
+ # 'bundler install --gemfile=NEW_GEMFILE'
265
+ next if File.basename(path) == 'bundler'
266
+
267
+ lines = File.readlines(path)
268
+ matched = false
269
+ filtered = lines.map do |l|
270
+ matched ||= (ENV_BUNDLE_GEMFILE_RX === l)
271
+ l.gsub(ENV_BUNDLE_GEMFILE_RX, '\\1=')
272
+ end
273
+ if !matched
274
+ raise UnexpectedBinstub, "expected #{path} to contain a line looking like ENV['BUNDLE_GEMFILE'] ||= but could not find one"
275
+ end
276
+ File.open(path, 'w') do |io|
277
+ io.write filtered.join("")
278
+ end
279
+ end
280
+
281
+ env['PATH'] << File.join(autoproj_install_dir, 'bin')
282
+ if private_autoproj?
283
+ env['GEM_PATH'] << autoproj_install_dir
284
+ end
179
285
  end
180
286
 
181
287
  def update_configuration
@@ -192,25 +298,92 @@ export AUTOPROJ_CURRENT_ROOT=#{root_dir}
192
298
  end
193
299
  end
194
300
 
301
+ def find_in_clean_path(command)
302
+ clean_path = env_for_child['PATH'].split(File::PATH_SEPARATOR)
303
+ clean_path.each do |p|
304
+ full_path = File.join(p, command)
305
+ if File.file?(full_path)
306
+ return full_path
307
+ end
308
+ end
309
+ nil
310
+ end
311
+
312
+ def find_bundler
313
+ clean_env = env_for_child
314
+ Gem.paths = Hash[
315
+ 'GEM_HOME' => clean_env['GEM_HOME'] || Gem.default_dir,
316
+ 'GEM_PATH' => clean_env['GEM_PATH'] || nil
317
+ ]
318
+ # Here, we're getting into the esotheric
319
+ #
320
+ # The problem is that e.g. Ubuntu and Debian install an
321
+ # operating_system.rb file that sets proper OS defaults. Some
322
+ # autoproj installs have it in their RUBYLIB but should not
323
+ # because of limitations of autoproj 1.x. This leads to
324
+ # Gem.bindir being *not* valid for subprocesses
325
+ #
326
+ # So, we're calling 'gem' as a subcommand to discovery the
327
+ # actual bindir
328
+ bindir = IO.popen(clean_env, [Gem.ruby, '-e', 'puts Gem.bindir']).read
329
+ if bindir
330
+ env['PATH'].unshift bindir.chomp
331
+ else
332
+ STDERR.puts "FATAL: cannot run #{Gem.ruby} -e 'puts Gem.bindir'"
333
+ exit 1
334
+ end
335
+
336
+ bundler = find_in_clean_path('bundler')
337
+ if !bundler
338
+ clean_path = env_for_child['PATH']
339
+ STDERR.puts "FATAL: cannot find 'bundler' in PATH=#{clean_path}"
340
+ if ENV['PATH'] != clean_path
341
+ STDERR.puts " it appears that you already have some autoproj-generated env.sh loaded"
342
+ STDERR.puts " - if you are running 'autoproj upgrade', please contact the autoproj author at https://github.com/rock-core/autoproj/issues/new"
343
+ STDERR.puts " - if you are running an install, try again in a console where the env.sh is not loaded"
344
+ exit 1
345
+ else
346
+ STDERR.puts " the recommended action is to install it manually first by running 'gem install bundler'"
347
+ STDERR.puts " or call this command again with --private-bundler to have it installed in the workspace"
348
+ exit 1
349
+ end
350
+ end
351
+ bundler
352
+ end
353
+
195
354
  def install
196
355
  if private_bundler?
197
356
  puts "Installing bundler in #{bundler_install_dir}"
198
357
  bundler = install_bundler
358
+ else
359
+ bundler = find_bundler
360
+ puts "Detected bundler at #{bundler}"
199
361
  end
200
362
  save_gemfile
201
363
  puts "Installing autoproj in #{dot_autoproj}"
202
- install_autoproj(bundler || 'bundler')
364
+ install_autoproj(bundler)
203
365
  end
204
366
 
205
367
  # Actually perform the install
206
- def run
207
- install
208
- ENV['BUNDLE_GEMFILE'] = autoproj_gemfile_path
209
- require 'bundler'
210
- Bundler.setup
211
- require 'autobuild'
212
- save_env_sh
213
- update_configuration
368
+ def run(stage2: false)
369
+ if stage2
370
+ require 'autobuild'
371
+ save_env_sh
372
+ else
373
+ install
374
+
375
+ env_for_child.each do |k, v|
376
+ if v
377
+ ENV[k] = v
378
+ else
379
+ ENV.delete(k)
380
+ end
381
+ end
382
+ ENV['BUNDLE_GEMFILE'] = autoproj_gemfile_path
383
+ update_configuration
384
+ exec Gem.ruby, File.join(autoproj_install_dir, 'bin', 'autoproj'),
385
+ 'install-stage2', root_dir
386
+ end
214
387
  end
215
388
  end
216
389
  end