autoproj 2.7.1 → 2.8.0

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.
Files changed (44) hide show
  1. checksums.yaml +5 -5
  2. data/Rakefile +31 -1
  3. data/autoproj.gemspec +2 -0
  4. data/bin/alocate +3 -5
  5. data/bin/alog +3 -3
  6. data/bin/amake +3 -4
  7. data/bin/aup +4 -3
  8. data/bin/autoproj +1 -6
  9. data/bin/autoproj_bootstrap +153 -47
  10. data/bin/autoproj_install +153 -47
  11. data/lib/autoproj/autobuild_extensions/dsl.rb +5 -0
  12. data/lib/autoproj/bash_completion.rb +26 -0
  13. data/lib/autoproj/cli/base.rb +4 -4
  14. data/lib/autoproj/cli/build.rb +2 -3
  15. data/lib/autoproj/cli/main.rb +52 -2
  16. data/lib/autoproj/cli/main_global.rb +39 -0
  17. data/lib/autoproj/cli/osdeps.rb +2 -1
  18. data/lib/autoproj/cli/update.rb +13 -1
  19. data/lib/autoproj/configuration.rb +14 -2
  20. data/lib/autoproj/environment.rb +48 -31
  21. data/lib/autoproj/ops/install.rb +153 -47
  22. data/lib/autoproj/shell_completion.rb +164 -0
  23. data/lib/autoproj/templates/helpers.bash.erb +79 -0
  24. data/lib/autoproj/templates/helpers.zsh.erb +38 -0
  25. data/lib/autoproj/templates/main.bash.erb +35 -0
  26. data/lib/autoproj/templates/main.zsh.erb +9 -0
  27. data/lib/autoproj/templates/subcommand.bash.erb +50 -0
  28. data/lib/autoproj/templates/subcommand.zsh.erb +51 -0
  29. data/lib/autoproj/version.rb +1 -1
  30. data/lib/autoproj/workspace.rb +97 -19
  31. data/lib/autoproj/zsh_completion.rb +43 -0
  32. data/shell/autoproj_bash +67 -0
  33. data/shell/autoproj_zsh +26 -0
  34. data/shell/completion/alocate_bash +68 -0
  35. data/shell/completion/alocate_zsh +22 -0
  36. data/shell/completion/alog_bash +61 -0
  37. data/shell/completion/alog_zsh +20 -0
  38. data/shell/completion/amake_bash +77 -0
  39. data/shell/completion/amake_zsh +27 -0
  40. data/shell/completion/aup_bash +89 -0
  41. data/shell/completion/aup_zsh +34 -0
  42. data/shell/completion/autoproj_bash +1556 -0
  43. data/shell/completion/autoproj_zsh +1005 -0
  44. metadata +51 -3
@@ -13,7 +13,7 @@ def validate_options(selected_packages, options)
13
13
  options[:deps] = false
14
14
  end
15
15
  if options[:deps].nil?
16
- options[:deps] =
16
+ options[:deps] =
17
17
  !(options[:rebuild] || options[:force])
18
18
  end
19
19
  return selected_packages, options
@@ -78,11 +78,10 @@ def run(selected_packages, options)
78
78
  Autobuild.do_build = true
79
79
  ops.build_packages(source_packages, parallel: parallel)
80
80
  Autobuild.apply(source_packages, "autoproj-build", ['install'])
81
+ Main.run_post_command_hook(:build, ws, source_packages: source_packages)
81
82
  ensure
82
83
  export_env_sh
83
84
  end
84
85
  end
85
86
  end
86
87
  end
87
-
88
-
@@ -2,6 +2,8 @@
2
2
  require 'tty/color'
3
3
  require 'autoproj/cli/main_test'
4
4
  require 'autoproj/cli/main_plugin'
5
+ require 'autoproj/cli/main_global'
6
+ require 'autoproj/cli'
5
7
  require 'autoproj/reporter'
6
8
 
7
9
  module Autoproj
@@ -9,6 +11,12 @@ module CLI
9
11
  def self.basic_setup
10
12
  Encoding.default_internal = Encoding::UTF_8
11
13
  Encoding.default_external = Encoding::UTF_8
14
+
15
+ argv = ARGV.find_all { |arg| arg != "--no-plugins" }
16
+ if argv.size == ARGV.size
17
+ Autoproj::CLI.load_plugins
18
+ end
19
+ argv
12
20
  end
13
21
 
14
22
  class Main < Thor
@@ -26,6 +34,44 @@ class Main < Thor
26
34
  stop_on_unknown_option! :exec
27
35
  check_unknown_options! except: :exec
28
36
 
37
+ # @api private
38
+ #
39
+ # Run hooks defined for a given hook name
40
+ def self.run_post_command_hook(hook_name, ws, **args)
41
+ @post_command_hooks[hook_name].each do |hook|
42
+ hook.call(ws, args)
43
+ end
44
+ end
45
+
46
+ # Register a hook that should be called at a given event
47
+ #
48
+ # @overload register_post_command_hook(:update)
49
+ # @yieldparam [Workspace] ws
50
+ # @yieldparam [Hash] params
51
+ #
52
+ # Hook called after an update operation (from the CLI, either
53
+ # update or osdeps)
54
+ #
55
+ # The params contain :source_packages and :osdeps_packages,
56
+ # respectively the list of names of the source and osdeps packages
57
+ # selected for the update operation (NOT the list of packages
58
+ # actually updated)
59
+ #
60
+ # @overload register_post_command_hook(:build)
61
+ # @yieldparam [Workspace] ws
62
+ # @yieldparam [Hash] params
63
+ #
64
+ # Hook called after a build operation (from the CLI, build)
65
+ #
66
+ # The params contain :source_packages, the list of names of the
67
+ # source and osdeps packages selected for the update operation (NOT
68
+ # the list of packages actually updated)
69
+ def self.register_post_command_hook(hook_name, &block)
70
+ @post_command_hooks[hook_name.to_sym] << block
71
+ end
72
+
73
+ @post_command_hooks = Hash.new { |h, k| h[k] = Array.new }
74
+
29
75
  no_commands do
30
76
  def default_report_on_package_failures
31
77
  if options[:debug]
@@ -79,7 +125,7 @@ def bootstrap(*args)
79
125
  run_autoproj_cli(:bootstrap, :Bootstrap, Hash[], *args)
80
126
  end
81
127
 
82
- desc 'envsh', 'update the env.sh file'
128
+ desc 'envsh', 'update the environment files'
83
129
  def envsh
84
130
  run_autoproj_cli(:envsh, :Envsh, Hash[])
85
131
  end
@@ -163,7 +209,7 @@ def update(*packages)
163
209
  report_options[:on_package_failures] = :report
164
210
  end
165
211
 
166
- run_autoproj_cli(:update, :Update, report_options, *packages)
212
+ run_autoproj_cli(:update, :Update, report_options, *packages, run_hook: true)
167
213
  end
168
214
 
169
215
  desc 'build [PACKAGES]', 'build packages'
@@ -466,6 +512,9 @@ def install_stage2(root_dir, *vars)
466
512
  desc 'plugin', 'interface to manage autoproj plugins'
467
513
  subcommand 'plugin', MainPlugin
468
514
 
515
+ desc 'global', 'global management of the known workspaces'
516
+ subcommand 'global', MainGlobal
517
+
469
518
  desc 'patch', 'applies patches necessary for the selected package',
470
519
  hide: true
471
520
  def patch(*packages)
@@ -518,3 +567,4 @@ def which(cmd)
518
567
  end
519
568
  end
520
569
  end
570
+
@@ -0,0 +1,39 @@
1
+ module Autoproj
2
+ module CLI
3
+ class MainGlobal < Thor
4
+ namespace 'global'
5
+
6
+ desc 'register', 'register the current workspace'
7
+ def register
8
+ require 'autoproj'
9
+ ws = Workspace.default
10
+ ws.load_config
11
+ ws.register_workspace
12
+ end
13
+
14
+ desc 'status', 'display information about the known workspaces'
15
+ def status
16
+ require 'autoproj'
17
+ ws = Workspace.registered_workspaces
18
+ fields = Workspace::RegisteredWorkspace.members.map(&:to_s)
19
+ format_w = fields.map(&:length).max + 1
20
+ format = "%-#{format_w}s %s (%s)"
21
+ blocks = ws.map do |w|
22
+ %w[root_dir prefix_dir build_dir].map do |name|
23
+ dir = w.public_send(name)
24
+ if dir.start_with?('/')
25
+ status = if File.directory?(dir)
26
+ Autobuild.color('present', :green)
27
+ else
28
+ Autobuild.color('absent', :yellow)
29
+ end
30
+
31
+ format(format, "#{name}:", dir, status)
32
+ end
33
+ end.compact.join("\n")
34
+ end
35
+ puts blocks.join("---\n")
36
+ end
37
+ end
38
+ end
39
+ end
@@ -29,8 +29,9 @@ def run(user_selection, update: true, **options)
29
29
  run_package_managers_without_packages: true,
30
30
  install_only: !update)
31
31
  export_env_sh(shell_helpers: shell_helpers)
32
+ Main.run_post_command_hook(:update, ws, source_packages: [],
33
+ osdep_packages: osdep_packages)
32
34
  end
33
35
  end
34
36
  end
35
37
  end
36
-
@@ -66,7 +66,7 @@ def validate_options(selection, options)
66
66
  return selection, options
67
67
  end
68
68
 
69
- def run(selected_packages, options)
69
+ def run(selected_packages, run_hook: false, **options)
70
70
  ws.manifest.accept_unavailable_osdeps = !options[:osdeps]
71
71
  ws.setup
72
72
  ws.autodetect_operating_system(force: true)
@@ -127,6 +127,18 @@ def run(selected_packages, options)
127
127
  ws.install_os_packages(osdep_packages, **osdeps_options)
128
128
  end
129
129
 
130
+ if run_hook
131
+ if options[:osdeps]
132
+ CLI::Main.run_post_command_hook(:update, ws,
133
+ source_packages: source_packages,
134
+ osdep_packages: osdep_packages)
135
+ else
136
+ CLI::Main.run_post_command_hook(:update, ws,
137
+ source_packages: source_packages,
138
+ osdep_packages: [])
139
+ end
140
+ end
141
+
130
142
  export_env_sh
131
143
 
132
144
  if !options[:auto_exclude]
@@ -344,7 +344,7 @@ def apply_autobuild_configuration
344
344
  end
345
345
  end
346
346
  end
347
-
347
+
348
348
  # A cache directory for autobuild's importers
349
349
  def importer_cache_dir
350
350
  get('importer_cache_dir', nil)
@@ -367,6 +367,18 @@ def prefix_dir
367
367
  get('prefix', 'install')
368
368
  end
369
369
 
370
+ # Sets the shells used in this workspace.
371
+ def user_shells=(shells)
372
+ set('user_shells', shells, true)
373
+ end
374
+
375
+ # The shells used in this workspace.
376
+ #
377
+ # @return [Array<String>]
378
+ def user_shells
379
+ get('user_shells', [])
380
+ end
381
+
370
382
  # Defines the temporary area in which packages should put their build
371
383
  # files
372
384
  #
@@ -433,7 +445,7 @@ def randomize_layout=(value)
433
445
  'test' => false]
434
446
 
435
447
  # The configuration key that should be used to store the utility
436
- # enable/disable information
448
+ # enable/disable information
437
449
  #
438
450
  # @param [String] the utility name
439
451
  # @return [String] the config key
@@ -24,38 +24,55 @@ def export_env_sh(subdir = nil, options = Hash.new)
24
24
  options = validate_options options,
25
25
  shell_helpers: true
26
26
 
27
- filename = if subdir
28
- File.join(root_dir, subdir, ENV_FILENAME)
29
- else
30
- File.join(root_dir, ENV_FILENAME)
31
- end
32
-
33
27
  shell_dir = File.expand_path(File.join("..", "..", "shell"), File.dirname(__FILE__))
34
- if options[:shell_helpers]
35
- source_after(File.join(shell_dir, "autoproj_sh"))
36
- end
28
+ completion_dir = File.join(shell_dir, 'completion')
29
+ env_updated = false
37
30
 
38
- existing_content =
39
- begin File.read(filename)
40
- rescue SystemCallError
31
+ (['sh'] + Autoproj.workspace.config.user_shells).to_set.each do |shell|
32
+ env_filename = if shell == 'sh'
33
+ ENV_FILENAME
34
+ else
35
+ (Pathname(ENV_FILENAME).sub_ext '').to_s.concat(".#{shell}")
36
+ end
37
+
38
+ filename = if subdir
39
+ File.join(root_dir, subdir, env_filename)
40
+ else
41
+ File.join(root_dir, env_filename)
41
42
  end
42
43
 
43
- StringIO.open(new_content = String.new, 'w') do |io|
44
- if inherit?
45
- io.write <<-EOF
46
- if test -n "$AUTOPROJ_CURRENT_ROOT" && test "$AUTOPROJ_CURRENT_ROOT" != "#{root_dir}"; then
47
- echo "the env.sh from $AUTOPROJ_CURRENT_ROOT is already loaded. Start a new shell before sourcing this one"
48
- return
49
- fi
50
- EOF
44
+ helper = File.join(shell_dir, "autoproj_#{shell}")
45
+ if options[:shell_helpers]
46
+ source_after(helper, shell: shell) if File.file?(helper)
47
+ %w[alocate alog amake aup autoproj].each do |tool|
48
+ completion_file = File.join(completion_dir, "#{tool}_#{shell}")
49
+ source_after(completion_file, shell: shell) if File.file?(completion_file)
50
+ end
51
51
  end
52
- super(io)
53
- end
54
52
 
55
- if new_content != existing_content
56
- Ops.atomic_write(filename) { |io| io.write new_content }
57
- true
53
+ existing_content =
54
+ begin File.read(filename)
55
+ rescue SystemCallError
56
+ end
57
+
58
+ StringIO.open(new_content = String.new, 'w') do |io|
59
+ if inherit?
60
+ io.write <<-EOF
61
+ if test -n "$AUTOPROJ_CURRENT_ROOT" && test "$AUTOPROJ_CURRENT_ROOT" != "#{root_dir}"; then
62
+ echo "the env.sh from $AUTOPROJ_CURRENT_ROOT is already loaded. Start a new shell before sourcing this one"
63
+ return
64
+ fi
65
+ EOF
66
+ end
67
+ super(io, shell: shell)
68
+ end
69
+
70
+ if new_content != existing_content
71
+ Ops.atomic_write(filename) { |io| io.write new_content }
72
+ env_updated = true
73
+ end
58
74
  end
75
+ env_updated
59
76
  end
60
77
  end
61
78
 
@@ -76,16 +93,16 @@ def self.env_add_path(name, *value)
76
93
  env.add_path(name, *value)
77
94
  end
78
95
  # @deprecated call Autoproj.env.source_after instead
79
- def self.env_source_file(file)
80
- env.source_after(file)
96
+ def self.env_source_file(file, shell: 'sh')
97
+ env.source_after(file, shell: shell)
81
98
  end
82
99
  # @deprecated call Autoproj.env.source_after instead
83
- def self.env_source_after(file)
84
- env.source_after(file)
100
+ def self.env_source_after(file, shell: 'sh')
101
+ env.source_after(file, shell: shell)
85
102
  end
86
103
  # @deprecated call Autoproj.env.source_before instead
87
- def self.env_source_before(file)
88
- env.source_before(file)
104
+ def self.env_source_before(file, shell: 'sh')
105
+ env.source_before(file, shell: shell)
89
106
  end
90
107
  # @deprecated call Autoproj.env.inherit instead
91
108
  def self.env_inherit(*names)
@@ -47,13 +47,15 @@ def initialize(root_dir)
47
47
 
48
48
  load_config
49
49
  if config['ruby_executable'] != Gem.ruby
50
- raise "this autoproj installation was already bootstrapped using #{config['ruby_executable']}, but you are currently running under #{Gem.ruby}. Changing the ruby interpreter in a given workspace is not supported, you need to do a clean bootstrap"
50
+ raise "this autoproj installation was already bootstrapped using "\
51
+ "#{config['ruby_executable']}, but you are currently running "\
52
+ "under #{Gem.ruby}. Changing the ruby interpreter in a given "\
53
+ "workspace is not supported, you need to do a clean bootstrap"
51
54
  end
52
55
  @ruby_executable = config['ruby_executable']
53
56
  @local = false
54
57
 
55
- default_gem_path = File.join(Dir.home, '.autoproj', 'gems')
56
- @gems_install_path = default_gem_path
58
+ install_gems_in_gem_user_dir
57
59
  end
58
60
 
59
61
  def env_for_child
@@ -132,13 +134,15 @@ def gem_path_suffix
132
134
  #
133
135
  # They are installed in a versioned subdirectory of this path, e.g.
134
136
  # {#gem_path_suffix}.
135
- #
137
+ #
136
138
  # @return [String]
137
139
  attr_reader :gems_install_path
138
140
  # The GEM_HOME under which the workspace's gems should be installed
139
- #
141
+ #
140
142
  # @return [String]
141
- def gems_gem_home; File.join(gems_install_path, gem_path_suffix) end
143
+ def gems_gem_home
144
+ File.join(gems_install_path, gem_path_suffix)
145
+ end
142
146
  # Sets where the workspace's gems should be installed
143
147
  #
144
148
  # @param [String] path the absolute path that should be given to
@@ -147,17 +151,41 @@ def gems_gem_home; File.join(gems_install_path, gem_path_suffix) end
147
151
  def gems_install_path=(path)
148
152
  @gems_install_path = path
149
153
  end
154
+
155
+ private def xdg_var(varname, default)
156
+ if (env = ENV[varname]) && !env.empty?
157
+ env
158
+ else
159
+ default
160
+ end
161
+ end
162
+
150
163
  # Install autoproj in Gem's default user dir
151
164
  def install_gems_in_gem_user_dir
152
- @gems_install_path = File.join(Gem.user_home, '.gem')
165
+ xdg_default_gem_path = xdg_var('XDG_DATA_HOME',
166
+ File.join(Dir.home, '.local', 'share', 'autoproj', 'gems'))
167
+ default_gem_path = File.join(
168
+ Dir.home, '.autoproj', 'gems')
169
+ @gems_install_path =
170
+ if File.directory?(xdg_default_gem_path)
171
+ xdg_default_gem_path
172
+ elsif File.directory?(default_gem_path)
173
+ default_gem_path
174
+ else
175
+ xdg_default_gem_path
176
+ end
153
177
  end
154
178
 
155
179
  # Whether autoproj should prefer OS-independent packages over their
156
180
  # OS-packaged equivalents (e.g. the thor gem vs. the ruby-thor
157
181
  # Debian package)
158
- def prefer_indep_over_os_packages?; @prefer_indep_over_os_packages end
182
+ def prefer_indep_over_os_packages?
183
+ @prefer_indep_over_os_packages
184
+ end
159
185
  # (see #prefer_index_over_os_packages?)
160
- def prefer_indep_over_os_packages=(flag); @prefer_indep_over_os_packages = !!flag end
186
+ def prefer_indep_over_os_packages=(flag)
187
+ @prefer_indep_over_os_packages = !!flag
188
+ end
161
189
 
162
190
  def self.guess_gem_program
163
191
  ruby_bin = RbConfig::CONFIG['RUBY_INSTALL_NAME']
@@ -165,7 +193,7 @@ def self.guess_gem_program
165
193
 
166
194
  candidates = ['gem']
167
195
  if ruby_bin =~ /^ruby(.+)$/
168
- candidates.unshift "gem#{$1}"
196
+ candidates.unshift "gem#{$1}"
169
197
  end
170
198
 
171
199
  candidates.each do |gem_name|
@@ -173,7 +201,8 @@ def self.guess_gem_program
173
201
  return gem_full_path
174
202
  end
175
203
  end
176
- raise ArgumentError, "cannot find a gem program (tried #{candidates.sort.join(", ")} in #{ruby_bindir})"
204
+ raise ArgumentError, "cannot find a gem program "\
205
+ "(tried #{candidates.sort.join(", ")} in #{ruby_bindir})"
177
206
  end
178
207
 
179
208
  # The content of the default {#gemfile}
@@ -197,39 +226,48 @@ def parse_options(args = ARGV)
197
226
  opt.on '--skip-stage2', 'do not run the stage2 install' do
198
227
  @skip_stage2 = true
199
228
  end
200
- opt.on '--gem-source=URL', String, "use this source for RubyGems instead of rubygems.org" do |url|
229
+ opt.on '--gem-source=URL', String, "use this source for RubyGems "\
230
+ "instead of rubygems.org" do |url|
201
231
  @gem_source = url
202
232
  end
203
- opt.on '--gems-path=PATH', "install gems under this path instead of ~/.autoproj/gems" do |path|
233
+ opt.on '--gems-path=PATH', "install gems under this path instead "\
234
+ "of ~/.autoproj/gems" do |path|
204
235
  self.gems_install_path = path
205
236
  end
206
237
  opt.on '--public-gems', "install gems in the default gem location" do
207
238
  self.install_gems_in_gem_user_dir
208
239
  end
209
- opt.on '--version=VERSION_CONSTRAINT', String, 'use the provided string as a version constraint for autoproj' do |version|
240
+ opt.on '--version=VERSION_CONSTRAINT', String, 'use the provided "\
241
+ "string as a version constraint for autoproj' do |version|
210
242
  if @gemfile
211
243
  raise "cannot give both --version and --gemfile"
212
244
  end
213
245
  @gemfile = default_gemfile_contents(version)
214
246
  end
215
- opt.on '--gemfile=PATH', String, 'use the given Gemfile to install autoproj instead of the default' do |path|
247
+ opt.on '--gemfile=PATH', String, 'use the given Gemfile to install "\
248
+ "autoproj instead of the default' do |path|
216
249
  if @gemfile
217
250
  raise "cannot give both --version and --gemfile"
218
251
  end
219
252
  @gemfile = File.read(path)
220
253
  end
221
- opt.on '--seed-config=PATH', String, 'path to a seed file that should be used to initialize the configuration' do |path|
254
+ opt.on '--seed-config=PATH', String, 'path to a seed file that "\
255
+ "should be used to initialize the configuration' do |path|
222
256
  @config.merge!(YAML.load(File.read(path)))
223
257
  end
224
- opt.on '--prefer-os-independent-packages', 'prefer OS-independent packages (such as a RubyGem) over their OS-packaged equivalent (e.g. the thor gem vs. the ruby-thor debian package)' do
258
+ opt.on '--prefer-os-independent-packages', 'prefer OS-independent "\
259
+ "packages (such as a RubyGem) over their OS-packaged equivalent "\
260
+ "(e.g. the thor gem vs. the ruby-thor debian package)' do
225
261
  @prefer_indep_over_os_packages = true
226
262
  end
227
- opt.on '--[no-]color', 'do not use colored output (enabled by default if the terminal supports it)' do |color|
263
+ opt.on '--[no-]color', 'do not use colored output (enabled by "\
264
+ "default if the terminal supports it)' do |color|
228
265
  if color then autoproj_options << "--color"
229
266
  else autoproj_options << '--no-color'
230
267
  end
231
268
  end
232
- opt.on '--[no-]progress', 'do not use progress output (enabled by default if the terminal supports it)' do |color|
269
+ opt.on '--[no-]progress', 'do not use progress output (enabled by "\
270
+ "default if the terminal supports it)' do |color|
233
271
  if color then autoproj_options << "--progress"
234
272
  else autoproj_options << '--no-progress'
235
273
  end
@@ -262,9 +300,11 @@ def install_bundler(gem_program, silent: false)
262
300
 
263
301
  result = system(
264
302
  env_for_child.merge('GEM_HOME' => gems_gem_home),
265
- Gem.ruby, gem_program, 'install', '--env-shebang', '--no-document', '--no-format-executable', '--clear-sources', '--source', gem_source,
266
- *local,
267
- "--bindir=#{File.join(gems_gem_home, 'bin')}", 'bundler', **redirection)
303
+ Gem.ruby, gem_program, 'install',
304
+ '--env-shebang', '--no-document', '--no-format-executable',
305
+ '--clear-sources', '--source', gem_source,
306
+ *local, "--bindir=#{File.join(gems_gem_home, 'bin')}",
307
+ 'bundler', **redirection)
268
308
 
269
309
  if !result
270
310
  STDERR.puts "FATAL: failed to install bundler in #{gems_gem_home}"
@@ -275,14 +315,15 @@ def install_bundler(gem_program, silent: false)
275
315
  if File.exist?(bundler_path)
276
316
  bundler_path
277
317
  else
278
- STDERR.puts "gem install bundler returned successfully, but still cannot find bundler in #{bundler_path}"
318
+ STDERR.puts "gem install bundler returned successfully, but still "\
319
+ "cannot find bundler in #{bundler_path}"
279
320
  nil
280
321
  end
281
322
  end
282
323
 
283
324
  def install_autoproj(bundler)
284
- # Force bundler to update. If the user does not want this, let him specify a
285
- # Gemfile with tighter version constraints
325
+ # Force bundler to update. If the user does not want this, let
326
+ # him specify a Gemfile with tighter version constraints
286
327
  lockfile = File.join(dot_autoproj, 'Gemfile.lock')
287
328
  if File.exist?(lockfile)
288
329
  FileUtils.rm lockfile
@@ -294,6 +335,7 @@ def install_autoproj(bundler)
294
335
  opts << '--local' if local?
295
336
  opts << "--path=#{gems_install_path}"
296
337
  shims_path = File.join(dot_autoproj, 'bin')
338
+
297
339
  result = system(clean_env,
298
340
  Gem.ruby, bundler, 'install',
299
341
  "--gemfile=#{autoproj_gemfile_path}",
@@ -306,12 +348,14 @@ def install_autoproj(bundler)
306
348
  exit 1
307
349
  end
308
350
  ensure
309
- self.class.rewrite_shims(shims_path, ruby_executable, root_dir, autoproj_gemfile_path, gems_gem_home)
351
+ self.class.rewrite_shims(shims_path, ruby_executable,
352
+ root_dir, autoproj_gemfile_path, gems_gem_home)
310
353
  end
311
354
 
312
355
  EXCLUDED_FROM_SHIMS = %w{rake thor}
313
356
 
314
- def self.rewrite_shims(shim_path, ruby_executable, root_dir, autoproj_gemfile_path, gems_gem_home)
357
+ def self.rewrite_shims(shim_path, ruby_executable,
358
+ root_dir, autoproj_gemfile_path, gems_gem_home)
315
359
  FileUtils.mkdir_p shim_path
316
360
  File.open(File.join(shim_path, 'ruby'), 'w') do |io|
317
361
  io.puts "#! /bin/sh"
@@ -319,10 +363,9 @@ def self.rewrite_shims(shim_path, ruby_executable, root_dir, autoproj_gemfile_pa
319
363
  end
320
364
  FileUtils.chmod 0755, File.join(shim_path, 'ruby')
321
365
 
322
- FileUtils.touch File.join(shim_path, 'bundler')
323
- FileUtils.touch File.join(shim_path, 'bundle')
324
366
  Dir.glob(File.join(shim_path, '*')) do |bin_script|
325
- next if !File.file?(bin_script)
367
+ next unless File.file?(bin_script)
368
+
326
369
  bin_name = File.basename(bin_script)
327
370
  if EXCLUDED_FROM_SHIMS.include?(bin_name)
328
371
  FileUtils.rm_f bin_script
@@ -332,19 +375,46 @@ def self.rewrite_shims(shim_path, ruby_executable, root_dir, autoproj_gemfile_pa
332
375
 
333
376
  bin_shim = File.join(shim_path, bin_name)
334
377
  bin_script_lines = File.readlines(bin_script)
378
+ next if has_autoproj_preamble?(bin_script_lines)
379
+
335
380
  File.open(bin_shim, 'w') do |io|
336
381
  if bin_name == 'bundler' || bin_name == 'bundle'
337
- io.puts shim_bundler(ruby_executable, autoproj_gemfile_path, gems_gem_home)
382
+ io.puts shim_bundler(bin_script_lines, ruby_executable,
383
+ autoproj_gemfile_path, gems_gem_home)
338
384
  else
339
- load_line = bin_script_lines.grep(/load Gem.bin_path/).first
340
- io.puts shim_script(ruby_executable, root_dir, autoproj_gemfile_path, gems_gem_home, load_line)
385
+ io.puts shim_script(bin_script_lines, ruby_executable, root_dir,
386
+ autoproj_gemfile_path, gems_gem_home)
341
387
  end
342
388
  end
343
389
  FileUtils.chmod 0755, bin_shim
344
390
  end
345
391
  end
346
392
 
347
- def self.shim_bundler(ruby_executable, autoproj_gemfile_path, gems_gem_home)
393
+ def self.new_style_bundler_binstub?(script_lines)
394
+ script_lines.any? { |l| l =~ /This file was generated by Bundler/ }
395
+ end
396
+
397
+ def self.has_autoproj_preamble?(script_lines)
398
+ script_lines.any? { |l| l =~ /Autoproj generated preamble/ }
399
+ end
400
+
401
+ def self.shim_bundler(script_lines, ruby_executable, autoproj_gemfile_path, gems_gem_home)
402
+ return shim_bundler_old(ruby_executable, autoproj_gemfile_path, gems_gem_home) \
403
+ unless new_style_bundler_binstub?(script_lines)
404
+
405
+ script_lines.insert(1, <<-RESTART_BUNDLER)
406
+ # Autoproj generated preamble
407
+ if defined?(Bundler)
408
+ Bundler.with_clean_env do
409
+ exec($0, *ARGV)
410
+ end
411
+ end
412
+ ENV['BUNDLE_GEMFILE'] = '#{autoproj_gemfile_path}'
413
+ RESTART_BUNDLER
414
+ script_lines.join
415
+ end
416
+
417
+ def self.shim_bundler_old(ruby_executable, autoproj_gemfile_path, gems_gem_home)
348
418
  "#! #{ruby_executable}
349
419
 
350
420
  if defined?(Bundler)
@@ -360,8 +430,35 @@ def self.shim_bundler(ruby_executable, autoproj_gemfile_path, gems_gem_home)
360
430
 
361
431
  load Gem.bin_path('bundler', 'bundler')"
362
432
  end
363
-
364
- def self.shim_script(ruby_executable, root_dir, autoproj_gemfile_path, gems_gem_home, load_line)
433
+
434
+ def self.shim_script(script_lines, ruby_executable, root_dir,
435
+ autoproj_gemfile_path, gems_gem_home)
436
+ new_style = !script_lines.empty? && script_lines.any? do |l|
437
+ l =~ /This file was generated by Bundler/
438
+ end
439
+ load_line = script_lines.grep(/load Gem.bin_path/).first
440
+ return shim_script_old(ruby_executable, root_dir,
441
+ autoproj_gemfile_path, gems_gem_home, load_line) \
442
+ unless new_style
443
+
444
+ script_lines.insert(1, <<-AUTOPROJ_PREAMBLE)
445
+ # Autoproj generated preamble, v1
446
+ if defined?(Bundler)
447
+ Bundler.with_clean_env do
448
+ exec(Hash['RUBYLIB' => nil], $0, *ARGV)
449
+ end
450
+ elsif ENV['RUBYLIB']
451
+ exec(Hash['RUBYLIB' => nil], $0, *ARGV)
452
+ end
453
+
454
+ ENV['BUNDLE_GEMFILE'] = '#{autoproj_gemfile_path}'
455
+ ENV['AUTOPROJ_CURRENT_ROOT'] = '#{root_dir}'
456
+ AUTOPROJ_PREAMBLE
457
+ return script_lines.join
458
+ end
459
+
460
+ def self.shim_script_old(ruby_executable, root_dir, autoproj_gemfile_path,
461
+ gems_gem_home, load_line)
365
462
  "#! #{ruby_executable}
366
463
 
367
464
  if defined?(Bundler)
@@ -423,9 +520,10 @@ def save_gemfile
423
520
  "if File.file?(config_path)",
424
521
  " require 'yaml'",
425
522
  " config = YAML.load(File.read(config_path)) || Hash.new",
426
- " (config['plugins'] || Hash.new).each do |plugin_name, (version, options)|",
427
- " gem plugin_name, version, **options",
428
- " end",
523
+ " (config['plugins'] || Hash.new).",
524
+ " each do |plugin_name, (version, options)|",
525
+ " gem plugin_name, version, **options",
526
+ " end",
429
527
  "end"
430
528
  ].join("\n")
431
529
 
@@ -439,7 +537,8 @@ def save_gemfile
439
537
 
440
538
 
441
539
  def find_in_clean_path(command, *additional_paths)
442
- clean_path = env_for_child['PATH'].split(File::PATH_SEPARATOR) + additional_paths
540
+ clean_path = env_for_child['PATH'].split(File::PATH_SEPARATOR) +
541
+ additional_paths
443
542
  clean_path.each do |p|
444
543
  full_path = File.join(p, command)
445
544
  if File.file?(full_path)
@@ -463,7 +562,8 @@ def gem_bindir
463
562
  #
464
563
  # So, we're calling 'gem' as a subcommand to discovery the
465
564
  # actual bindir
466
- bindir = IO.popen(env_for_child, [Gem.ruby, '-e', 'puts "#{Gem.user_dir}/bin"']).read
565
+ bindir = IO.popen(env_for_child,
566
+ [Gem.ruby, '-e', 'puts "#{Gem.user_dir}/bin"']).read
467
567
  if bindir
468
568
  @gem_bindir = bindir.chomp
469
569
  else
@@ -473,7 +573,9 @@ def gem_bindir
473
573
 
474
574
  def install
475
575
  if ENV['BUNDLER_GEMFILE']
476
- raise "cannot run autoproj_install or autoproj_bootstrap while under a 'bundler exec' subcommand or having loaded an env.sh. Open a new console and try again"
576
+ raise "cannot run autoproj_install or autoproj_bootstrap while "\
577
+ "under a 'bundler exec' subcommand or having loaded an env.sh. "\
578
+ "Open a new console and try again"
477
579
  end
478
580
 
479
581
  gem_program = self.class.guess_gem_program
@@ -503,7 +605,7 @@ def install
503
605
 
504
606
  def load_config
505
607
  v1_config_path = File.join(root_dir, 'autoproj', 'config.yml')
506
-
608
+
507
609
  config = Hash.new
508
610
  if File.file?(v1_config_path)
509
611
  config.merge!(YAML.load(File.read(v1_config_path)) || Hash.new)
@@ -517,7 +619,10 @@ def load_config
517
619
  ruby_executable = File.join(ruby_bindir, ruby)
518
620
  if current = config['ruby_executable'] # When upgrading or reinstalling
519
621
  if current != ruby_executable
520
- raise "this workspace has already been initialized using #{current}, you cannot run autoproj install with #{ruby_executable}. If you know what you're doing, delete the ruby_executable line in config.yml and try again"
622
+ raise "this workspace has already been initialized using "\
623
+ "#{current}, you cannot run autoproj install with "\
624
+ "#{ruby_executable}. If you know what you're doing, "\
625
+ "delete the ruby_executable line in config.yml and try again"
521
626
  end
522
627
  else
523
628
  config['ruby_executable'] = ruby_executable
@@ -576,18 +681,19 @@ def stage2(*vars)
576
681
  save_env_sh(*vars)
577
682
  puts "running 'autoproj envsh' to generate a proper env.sh"
578
683
  if !system(Gem.ruby, autoproj_path, 'envsh', *autoproj_options)
579
- STDERR.puts "failed to run autoproj envsh on the newly installed autoproj (#{autoproj_path})"
684
+ STDERR.puts "failed to run autoproj envsh on the newly installed "\
685
+ "autoproj (#{autoproj_path})"
580
686
  exit 1
581
687
  end
582
688
  # This is really needed on an existing install to install the
583
689
  # gems that were present in the v1 layout
584
690
  puts "running 'autoproj osdeps' to re-install missing gems"
585
691
  if !system(Gem.ruby, autoproj_path, 'osdeps')
586
- STDERR.puts "failed to run autoproj osdeps on the newly installed autoproj (#{autoproj_path})"
692
+ STDERR.puts "failed to run autoproj osdeps on the newly installed "\
693
+ "autoproj (#{autoproj_path})"
587
694
  exit 1
588
695
  end
589
696
  end
590
697
  end
591
698
  end
592
699
  end
593
-