bin/autoproj_install in autoproj-2.7.1 vs bin/autoproj_install in autoproj-2.8.0
- old
+ new
@@ -55,17 +55,19 @@
env['PATH'] = self.class.sanitize_env(ENV['PATH'] || "")
env['BUNDLE_GEMFILE'] = []
load_config
if config['ruby_executable'] != Gem.ruby
- 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"
+ 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"
end
@ruby_executable = config['ruby_executable']
@local = false
- default_gem_path = File.join(Dir.home, '.autoproj', 'gems')
- @gems_install_path = default_gem_path
+ install_gems_in_gem_user_dir
end
def env_for_child
env.inject(Hash.new) do |h, (k, v)|
h[k] = if v && !v.empty? then v.join(File::PATH_SEPARATOR)
@@ -140,52 +142,79 @@
# The path into which the workspace's gems should be installed
#
# They are installed in a versioned subdirectory of this path, e.g.
# {#gem_path_suffix}.
- #
+ #
# @return [String]
attr_reader :gems_install_path
# The GEM_HOME under which the workspace's gems should be installed
- #
+ #
# @return [String]
- def gems_gem_home; File.join(gems_install_path, gem_path_suffix) end
+ def gems_gem_home
+ File.join(gems_install_path, gem_path_suffix)
+ end
# Sets where the workspace's gems should be installed
#
# @param [String] path the absolute path that should be given to
# bundler. The gems themselves will be installed in the
# {#gem_path_suffix} subdirectory under this
def gems_install_path=(path)
@gems_install_path = path
end
+
+ private def xdg_var(varname, default)
+ if (env = ENV[varname]) && !env.empty?
+ env
+ else
+ default
+ end
+ end
+
# Install autoproj in Gem's default user dir
def install_gems_in_gem_user_dir
- @gems_install_path = File.join(Gem.user_home, '.gem')
+ xdg_default_gem_path = xdg_var('XDG_DATA_HOME',
+ File.join(Dir.home, '.local', 'share', 'autoproj', 'gems'))
+ default_gem_path = File.join(
+ Dir.home, '.autoproj', 'gems')
+ @gems_install_path =
+ if File.directory?(xdg_default_gem_path)
+ xdg_default_gem_path
+ elsif File.directory?(default_gem_path)
+ default_gem_path
+ else
+ xdg_default_gem_path
+ end
end
# Whether autoproj should prefer OS-independent packages over their
# OS-packaged equivalents (e.g. the thor gem vs. the ruby-thor
# Debian package)
- def prefer_indep_over_os_packages?; @prefer_indep_over_os_packages end
+ def prefer_indep_over_os_packages?
+ @prefer_indep_over_os_packages
+ end
# (see #prefer_index_over_os_packages?)
- def prefer_indep_over_os_packages=(flag); @prefer_indep_over_os_packages = !!flag end
+ def prefer_indep_over_os_packages=(flag)
+ @prefer_indep_over_os_packages = !!flag
+ end
def self.guess_gem_program
ruby_bin = RbConfig::CONFIG['RUBY_INSTALL_NAME']
ruby_bindir = RbConfig::CONFIG['bindir']
candidates = ['gem']
if ruby_bin =~ /^ruby(.+)$/
- candidates.unshift "gem#{$1}"
+ candidates.unshift "gem#{$1}"
end
candidates.each do |gem_name|
if File.file?(gem_full_path = File.join(ruby_bindir, gem_name))
return gem_full_path
end
end
- raise ArgumentError, "cannot find a gem program (tried #{candidates.sort.join(", ")} in #{ruby_bindir})"
+ raise ArgumentError, "cannot find a gem program "\
+ "(tried #{candidates.sort.join(", ")} in #{ruby_bindir})"
end
# The content of the default {#gemfile}
#
# @param [String] autoproj_version a constraint on the autoproj version
@@ -205,43 +234,52 @@
@local = true
end
opt.on '--skip-stage2', 'do not run the stage2 install' do
@skip_stage2 = true
end
- opt.on '--gem-source=URL', String, "use this source for RubyGems instead of rubygems.org" do |url|
+ opt.on '--gem-source=URL', String, "use this source for RubyGems "\
+ "instead of rubygems.org" do |url|
@gem_source = url
end
- opt.on '--gems-path=PATH', "install gems under this path instead of ~/.autoproj/gems" do |path|
+ opt.on '--gems-path=PATH', "install gems under this path instead "\
+ "of ~/.autoproj/gems" do |path|
self.gems_install_path = path
end
opt.on '--public-gems', "install gems in the default gem location" do
self.install_gems_in_gem_user_dir
end
- opt.on '--version=VERSION_CONSTRAINT', String, 'use the provided string as a version constraint for autoproj' do |version|
+ opt.on '--version=VERSION_CONSTRAINT', String, 'use the provided "\
+ "string as a version constraint for autoproj' do |version|
if @gemfile
raise "cannot give both --version and --gemfile"
end
@gemfile = default_gemfile_contents(version)
end
- opt.on '--gemfile=PATH', String, 'use the given Gemfile to install autoproj instead of the default' do |path|
+ opt.on '--gemfile=PATH', String, 'use the given Gemfile to install "\
+ "autoproj instead of the default' do |path|
if @gemfile
raise "cannot give both --version and --gemfile"
end
@gemfile = File.read(path)
end
- opt.on '--seed-config=PATH', String, 'path to a seed file that should be used to initialize the configuration' do |path|
+ opt.on '--seed-config=PATH', String, 'path to a seed file that "\
+ "should be used to initialize the configuration' do |path|
@config.merge!(YAML.load(File.read(path)))
end
- 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
+ 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
@prefer_indep_over_os_packages = true
end
- opt.on '--[no-]color', 'do not use colored output (enabled by default if the terminal supports it)' do |color|
+ opt.on '--[no-]color', 'do not use colored output (enabled by "\
+ "default if the terminal supports it)' do |color|
if color then autoproj_options << "--color"
else autoproj_options << '--no-color'
end
end
- opt.on '--[no-]progress', 'do not use progress output (enabled by default if the terminal supports it)' do |color|
+ opt.on '--[no-]progress', 'do not use progress output (enabled by "\
+ "default if the terminal supports it)' do |color|
if color then autoproj_options << "--progress"
else autoproj_options << '--no-progress'
end
end
end
@@ -270,31 +308,34 @@
redirection = Hash[out: :close]
end
result = system(
env_for_child.merge('GEM_HOME' => gems_gem_home),
- Gem.ruby, gem_program, 'install', '--env-shebang', '--no-document', '--no-format-executable', '--clear-sources', '--source', gem_source,
- *local,
- "--bindir=#{File.join(gems_gem_home, 'bin')}", 'bundler', **redirection)
+ Gem.ruby, gem_program, 'install',
+ '--env-shebang', '--no-document', '--no-format-executable',
+ '--clear-sources', '--source', gem_source,
+ *local, "--bindir=#{File.join(gems_gem_home, 'bin')}",
+ 'bundler', **redirection)
if !result
STDERR.puts "FATAL: failed to install bundler in #{gems_gem_home}"
nil
end
bundler_path = File.join(gems_gem_home, 'bin', 'bundler')
if File.exist?(bundler_path)
bundler_path
else
- STDERR.puts "gem install bundler returned successfully, but still cannot find bundler in #{bundler_path}"
+ STDERR.puts "gem install bundler returned successfully, but still "\
+ "cannot find bundler in #{bundler_path}"
nil
end
end
def install_autoproj(bundler)
- # Force bundler to update. If the user does not want this, let him specify a
- # Gemfile with tighter version constraints
+ # Force bundler to update. If the user does not want this, let
+ # him specify a Gemfile with tighter version constraints
lockfile = File.join(dot_autoproj, 'Gemfile.lock')
if File.exist?(lockfile)
FileUtils.rm lockfile
end
@@ -302,10 +343,11 @@
opts = Array.new
opts << '--local' if local?
opts << "--path=#{gems_install_path}"
shims_path = File.join(dot_autoproj, 'bin')
+
result = system(clean_env,
Gem.ruby, bundler, 'install',
"--gemfile=#{autoproj_gemfile_path}",
"--shebang=#{Gem.ruby}",
"--binstubs=#{shims_path}",
@@ -314,49 +356,77 @@
if !result
STDERR.puts "FATAL: failed to install autoproj in #{dot_autoproj}"
exit 1
end
ensure
- self.class.rewrite_shims(shims_path, ruby_executable, root_dir, autoproj_gemfile_path, gems_gem_home)
+ self.class.rewrite_shims(shims_path, ruby_executable,
+ root_dir, autoproj_gemfile_path, gems_gem_home)
end
EXCLUDED_FROM_SHIMS = %w{rake thor}
- def self.rewrite_shims(shim_path, ruby_executable, root_dir, autoproj_gemfile_path, gems_gem_home)
+ def self.rewrite_shims(shim_path, ruby_executable,
+ root_dir, autoproj_gemfile_path, gems_gem_home)
FileUtils.mkdir_p shim_path
File.open(File.join(shim_path, 'ruby'), 'w') do |io|
io.puts "#! /bin/sh"
io.puts "exec #{ruby_executable} \"$@\""
end
FileUtils.chmod 0755, File.join(shim_path, 'ruby')
- FileUtils.touch File.join(shim_path, 'bundler')
- FileUtils.touch File.join(shim_path, 'bundle')
Dir.glob(File.join(shim_path, '*')) do |bin_script|
- next if !File.file?(bin_script)
+ next unless File.file?(bin_script)
+
bin_name = File.basename(bin_script)
if EXCLUDED_FROM_SHIMS.include?(bin_name)
FileUtils.rm_f bin_script
next
end
next if bin_name == 'ruby'
bin_shim = File.join(shim_path, bin_name)
bin_script_lines = File.readlines(bin_script)
+ next if has_autoproj_preamble?(bin_script_lines)
+
File.open(bin_shim, 'w') do |io|
if bin_name == 'bundler' || bin_name == 'bundle'
- io.puts shim_bundler(ruby_executable, autoproj_gemfile_path, gems_gem_home)
+ io.puts shim_bundler(bin_script_lines, ruby_executable,
+ autoproj_gemfile_path, gems_gem_home)
else
- load_line = bin_script_lines.grep(/load Gem.bin_path/).first
- io.puts shim_script(ruby_executable, root_dir, autoproj_gemfile_path, gems_gem_home, load_line)
+ io.puts shim_script(bin_script_lines, ruby_executable, root_dir,
+ autoproj_gemfile_path, gems_gem_home)
end
end
FileUtils.chmod 0755, bin_shim
end
end
- def self.shim_bundler(ruby_executable, autoproj_gemfile_path, gems_gem_home)
+ def self.new_style_bundler_binstub?(script_lines)
+ script_lines.any? { |l| l =~ /This file was generated by Bundler/ }
+ end
+
+ def self.has_autoproj_preamble?(script_lines)
+ script_lines.any? { |l| l =~ /Autoproj generated preamble/ }
+ end
+
+ def self.shim_bundler(script_lines, ruby_executable, autoproj_gemfile_path, gems_gem_home)
+ return shim_bundler_old(ruby_executable, autoproj_gemfile_path, gems_gem_home) \
+ unless new_style_bundler_binstub?(script_lines)
+
+ script_lines.insert(1, <<-RESTART_BUNDLER)
+# Autoproj generated preamble
+if defined?(Bundler)
+ Bundler.with_clean_env do
+ exec($0, *ARGV)
+ end
+end
+ENV['BUNDLE_GEMFILE'] = '#{autoproj_gemfile_path}'
+ RESTART_BUNDLER
+ script_lines.join
+ end
+
+ def self.shim_bundler_old(ruby_executable, autoproj_gemfile_path, gems_gem_home)
"#! #{ruby_executable}
if defined?(Bundler)
Bundler.with_clean_env do
exec($0, *ARGV)
@@ -368,12 +438,39 @@
ENV.delete('GEM_PATH')
Gem.paths = Hash['GEM_HOME' => '#{gems_gem_home}', 'GEM_PATH' => '']
load Gem.bin_path('bundler', 'bundler')"
end
-
- def self.shim_script(ruby_executable, root_dir, autoproj_gemfile_path, gems_gem_home, load_line)
+
+ def self.shim_script(script_lines, ruby_executable, root_dir,
+ autoproj_gemfile_path, gems_gem_home)
+ new_style = !script_lines.empty? && script_lines.any? do |l|
+ l =~ /This file was generated by Bundler/
+ end
+ load_line = script_lines.grep(/load Gem.bin_path/).first
+ return shim_script_old(ruby_executable, root_dir,
+ autoproj_gemfile_path, gems_gem_home, load_line) \
+ unless new_style
+
+ script_lines.insert(1, <<-AUTOPROJ_PREAMBLE)
+# Autoproj generated preamble, v1
+if defined?(Bundler)
+ Bundler.with_clean_env do
+ exec(Hash['RUBYLIB' => nil], $0, *ARGV)
+ end
+elsif ENV['RUBYLIB']
+ exec(Hash['RUBYLIB' => nil], $0, *ARGV)
+end
+
+ENV['BUNDLE_GEMFILE'] = '#{autoproj_gemfile_path}'
+ENV['AUTOPROJ_CURRENT_ROOT'] = '#{root_dir}'
+ AUTOPROJ_PREAMBLE
+ return script_lines.join
+ end
+
+ def self.shim_script_old(ruby_executable, root_dir, autoproj_gemfile_path,
+ gems_gem_home, load_line)
"#! #{ruby_executable}
if defined?(Bundler)
Bundler.with_clean_env do
exec(Hash['RUBYLIB' => nil], $0, *ARGV)
@@ -431,13 +528,14 @@
"",
"config_path = File.join(__dir__, 'config.yml')",
"if File.file?(config_path)",
" require 'yaml'",
" config = YAML.load(File.read(config_path)) || Hash.new",
- " (config['plugins'] || Hash.new).each do |plugin_name, (version, options)|",
- " gem plugin_name, version, **options",
- " end",
+ " (config['plugins'] || Hash.new).",
+ " each do |plugin_name, (version, options)|",
+ " gem plugin_name, version, **options",
+ " end",
"end"
].join("\n")
FileUtils.mkdir_p File.dirname(autoproj_gemfile_path)
File.open(autoproj_gemfile_path, 'w') do |io|
@@ -447,11 +545,12 @@
ENV_BUNDLE_GEMFILE_RX = /^(\s*ENV\[['"]BUNDLE_GEMFILE['"]\]\s*)(?:\|\|)?=/
def find_in_clean_path(command, *additional_paths)
- clean_path = env_for_child['PATH'].split(File::PATH_SEPARATOR) + additional_paths
+ clean_path = env_for_child['PATH'].split(File::PATH_SEPARATOR) +
+ additional_paths
clean_path.each do |p|
full_path = File.join(p, command)
if File.file?(full_path)
return full_path
end
@@ -471,21 +570,24 @@
# because of limitations of autoproj 1.x. This leads to
# Gem.bindir being *not* valid for subprocesses
#
# So, we're calling 'gem' as a subcommand to discovery the
# actual bindir
- bindir = IO.popen(env_for_child, [Gem.ruby, '-e', 'puts "#{Gem.user_dir}/bin"']).read
+ bindir = IO.popen(env_for_child,
+ [Gem.ruby, '-e', 'puts "#{Gem.user_dir}/bin"']).read
if bindir
@gem_bindir = bindir.chomp
else
raise "FATAL: cannot run #{Gem.ruby} -e 'puts Gem.bindir'"
end
end
def install
if ENV['BUNDLER_GEMFILE']
- 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"
+ 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"
end
gem_program = self.class.guess_gem_program
puts "Detected 'gem' to be #{gem_program}"
env['GEM_HOME'] = [gems_gem_home]
@@ -511,11 +613,11 @@
install_autoproj(bundler)
end
def load_config
v1_config_path = File.join(root_dir, 'autoproj', 'config.yml')
-
+
config = Hash.new
if File.file?(v1_config_path)
config.merge!(YAML.load(File.read(v1_config_path)) || Hash.new)
end
if File.file?(autoproj_config_path)
@@ -525,11 +627,14 @@
ruby = RbConfig::CONFIG['RUBY_INSTALL_NAME']
ruby_bindir = RbConfig::CONFIG['bindir']
ruby_executable = File.join(ruby_bindir, ruby)
if current = config['ruby_executable'] # When upgrading or reinstalling
if current != ruby_executable
- 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"
+ 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"
end
else
config['ruby_executable'] = ruby_executable
end
@@ -584,24 +689,25 @@
require 'autobuild'
puts "saving temporary env.sh and .autoproj/env.sh"
save_env_sh(*vars)
puts "running 'autoproj envsh' to generate a proper env.sh"
if !system(Gem.ruby, autoproj_path, 'envsh', *autoproj_options)
- STDERR.puts "failed to run autoproj envsh on the newly installed autoproj (#{autoproj_path})"
+ STDERR.puts "failed to run autoproj envsh on the newly installed "\
+ "autoproj (#{autoproj_path})"
exit 1
end
# This is really needed on an existing install to install the
# gems that were present in the v1 layout
puts "running 'autoproj osdeps' to re-install missing gems"
if !system(Gem.ruby, autoproj_path, 'osdeps')
- STDERR.puts "failed to run autoproj osdeps on the newly installed autoproj (#{autoproj_path})"
+ STDERR.puts "failed to run autoproj osdeps on the newly installed "\
+ "autoproj (#{autoproj_path})"
exit 1
end
end
end
end
end
-
ENV.delete('BUNDLE_GEMFILE')
ENV.delete('RUBYLIB')
ops = Autoproj::Ops::Install.new(Dir.pwd)