autoproj 2.7.1 → 2.8.0

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