bin/autoproj_install in autoproj-2.0.0.rc9 vs bin/autoproj_install in autoproj-2.0.0.rc10
- old
+ new
@@ -35,24 +35,19 @@
@gemfile = File.read(autoproj_gemfile_path)
else
@gemfile = default_gemfile_contents
end
- load_config
- @local = false
- @env = self.class.clean_env
- end
-
- def self.clean_env
- env = Hash.new
+ @env = Hash.new
env['RUBYLIB'] = []
env['GEM_PATH'] = []
- %w{PATH GEM_HOME}.each do |name|
- env[name] = sanitize_env(ENV[name] || "")
- end
+ env['GEM_HOME'] = []
+ env['PATH'] = self.class.sanitize_env(ENV['PATH'] || "")
env['BUNDLE_GEMFILE'] = []
- env
+
+ load_config
+ @local = false
end
def env_for_child
env.inject(Hash.new) do |h, (k, v)|
h[k] = (v.join(File::PATH_SEPARATOR) if v && !v.empty?)
@@ -86,11 +81,11 @@
return false
end
def dot_autoproj; File.join(root_dir, '.autoproj') end
- def bundler_install_dir; File.join(dot_autoproj, 'bundler') end
+
def autoproj_install_dir; File.join(dot_autoproj, 'autoproj') end
# The path to the gemfile used to install autoproj
def autoproj_gemfile_path; File.join(autoproj_install_dir, 'Gemfile') end
def autoproj_config_path; File.join(dot_autoproj, 'config.yml') end
@@ -98,22 +93,51 @@
def local?; !!@local end
# (see #local?)
def local=(flag); @local = flag end
# Whether bundler should be installed locally in {#dot_autoproj}
- def private_bundler?; @private_bundler end
+ def private_bundler?; !!@private_bundler end
+ # The path to the directory into which the bundler gem should be
+ # installed
+ def bundler_gem_home; @private_bundler || gem_bindir end
# (see #private_bundler?)
- def private_bundler=(flag); @private_bundler = !!flag end
+ def private_bundler=(flag)
+ @private_bundler =
+ if flag.respond_to?(:to_str) then File.expand_path(flag)
+ elsif flag
+ File.join(dot_autoproj, 'bundler')
+ end
+ end
+
# Whether autoproj should be installed locally in {#dot_autoproj}
- def private_autoproj?; @private_autoproj end
+ def private_autoproj?; !!@private_autoproj end
+ # The path to the directory into which the autoproj gem should be
+ # installed
+ def autoproj_gem_home; @private_autoproj || gem_bindir end
# (see #private_autoproj?)
- def private_autoproj=(flag); @private_autoproj = !!flag end
- # Whether bundler should be installed locally in the workspace
- # prefix directory
- def private_gems?; @private_gems end
+ def private_autoproj=(flag)
+ @private_autoproj =
+ if flag.respond_to?(:to_str) then File.expand_path(flag)
+ elsif flag
+ File.join(dot_autoproj, 'autoproj')
+ end
+ end
+
+ # Whether autoproj should be installed locally in {#dot_autoproj}
+ #
+ # Unlike for {#private_autoproj?} and {#private_bundler?}, there is
+ # no default path to save the gems as we don't yet know the path to
+ # the prefix directory
+ def private_gems?; !!@private_gems end
# (see #private_gems?)
- def private_gems=(flag); @private_gems = !!flag end
+ def private_gems=(value)
+ @private_gems =
+ if value.respond_to?(:to_str) then File.expand_path(value)
+ else value
+ 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
# (see #private_gems?)
@@ -151,23 +175,23 @@
def parse_options(args = ARGV)
options = OptionParser.new do |opt|
opt.on '--local', 'do not access the network (may fail)' do
@local = true
end
- opt.on '--private-bundler', 'install bundler locally in the workspace' do
- @private_bundler = true
+ opt.on '--private-bundler[=PATH]', 'install bundler locally in the workspace' do |path|
+ self.private_bundler = path || true
end
- opt.on '--private-autoproj', 'install autoproj locally in the workspace' do
- @private_autoproj = true
+ opt.on '--private-autoproj[=PATH]', 'install autoproj locally in the workspace' do |path|
+ self.private_autoproj = path || true
end
- opt.on '--private-gems', 'install gems locally in the prefix directory' do
- @private_gems = true
+ opt.on '--private-gems[=PATH]', 'install gems locally in the prefix directory' do |path|
+ self.private_gems = path || true
end
- opt.on '--private', 'whether bundler, autoproj and the workspace gems should be installed locally in the workspace' do
- @private_bundler = true
- @private_autoproj = true
- @private_gems = true
+ opt.on '--private[=PATH]', 'whether bundler, autoproj and the workspace gems should be installed locally in the workspace' do |path|
+ self.private_bundler = path || true
+ self.private_autoproj = path || true
+ self.private_gems = path || true
end
opt.on '--version=VERSION_CONSTRAINT', String, 'use the provided string as a version constraint for autoproj' do |version|
@gemfile = default_gemfile_contents(version)
end
opt.on '--gemfile=PATH', String, 'use the given Gemfile to install autoproj instead of the default' do |path|
@@ -185,90 +209,98 @@
puts "Detected 'gem' to be #{gem_program}"
local = ['--local'] if local?
result = system(
- env_for_child.merge('GEM_PATH' => nil, 'GEM_HOME' => bundler_install_dir),
- gem_program, 'install', '--no-document', '--no-user-install', '--no-format-executable',
+ env_for_child.merge('GEM_PATH' => "", 'GEM_HOME' => bundler_gem_home),
+ gem_program, 'install', '--no-document', '--no-format-executable',
*local,
- "--bindir=#{File.join(bundler_install_dir, 'bin')}", 'bundler')
+ "--bindir=#{File.join(bundler_gem_home, 'bin')}", 'bundler')
if !result
STDERR.puts "FATAL: failed to install bundler in #{dot_autoproj}"
exit 1
end
- env['PATH'].unshift File.join(bundler_install_dir, 'bin')
- File.join(bundler_install_dir, 'bin', 'bundler')
+ File.join(bundler_gem_home, 'bin', 'bundler')
end
def find_bundler
- self.env['PATH'].unshift gem_bindir
clean_env = env_for_child
- Gem.paths = Hash[
- 'GEM_HOME' => clean_env['GEM_HOME'] || Gem.default_dir,
- 'GEM_PATH' => clean_env['GEM_PATH'] || nil
- ]
+ if bundler = find_in_clean_path('bundler', gem_bindir)
+ return bundler
+ end
- bundler = find_in_clean_path('bundler')
- if !bundler
- clean_path = env_for_child['PATH']
- STDERR.puts "cannot find 'bundler' in PATH=#{clean_path}"
- STDERR.puts "installing it now ..."
- result = system(clean_env, Gem.ruby, '-S', 'gem', 'install', 'bundler')
- if !result
- if ENV['PATH'] != clean_path
- STDERR.puts " it appears that you already have some autoproj-generated env.sh loaded"
- STDERR.puts " - if you are running 'autoproj upgrade', please contact the autoproj author at https://github.com/rock-core/autoproj/issues/new"
- STDERR.puts " - if you are running an install, try again in a console where the env.sh is not loaded"
- exit 1
- else
- STDERR.puts " the recommended action is to install it manually first by running 'gem install bundler'"
- STDERR.puts " or call this command again with --private-bundler to have it installed in the workspace"
- exit 1
- end
- end
+ clean_path = env_for_child['PATH']
+ STDERR.puts "cannot find 'bundler' in PATH=#{clean_path}#{File::PATH_SEPARATOR}#{gem_bindir}"
+ STDERR.puts "installing it now ..."
+ result = system(
+ clean_env.merge('GEM_PATH' => "", 'GEM_HOME' => bundler_gem_path),
+ Gem.ruby, '-S', 'gem', 'install', 'bundler')
- bundler = find_in_clean_path('bundler')
- if !bundler
- STDERR.puts "FATAL: gem install bundler returned successfully, but still cannot find bundler"
- STDERR.puts "FATAL: in #{clean_path}"
+ if !result
+ if ENV['PATH'] != clean_path
+ STDERR.puts " it appears that you already have some autoproj-generated env.sh loaded"
+ STDERR.puts " - if you are running 'autoproj upgrade', please contact the autoproj author at https://github.com/rock-core/autoproj/issues/new"
+ STDERR.puts " - if you are running an install, try again in a console where the env.sh is not loaded"
+ exit 1
+ else
+ STDERR.puts " the recommended action is to install it manually first by running 'gem install bundler'"
+ STDERR.puts " or call this command again with --private-bundler to have it installed in the workspace"
+ exit 1
end
end
- bundler
+ bundler = File.join(bundler_gem_path, 'bin', 'bundler')
+ if File.exist?(bundler)
+ bundler
+ else
+ STDERR.puts "gem install bundler returned successfully, but still cannot find bundler in #{bundler}"
+ 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
lockfile = File.join(autoproj_install_dir, 'Gemfile.lock')
if File.exist?(lockfile)
FileUtils.rm lockfile
end
- opts = Array.new
- clean_env = env_for_child.merge('BUNDLE_GEMFILE' => nil)
+ clean_env = env_for_child.dup
+ opts = Array.new
opts << '--local' if local?
if private_autoproj?
- clean_env['GEM_PATH'] = (bundler_install_dir if private_bundler?)
+ clean_env['GEM_PATH'] = bundler_gem_home
clean_env['GEM_HOME'] = nil
- opts << "--clean" << "--path=#{autoproj_install_dir}"
+ opts << "--clean" << "--path=#{autoproj_gem_home}"
end
binstubs_path = File.join(autoproj_install_dir, 'bin')
- result = system(clean_env,
+ result = system(clean_env.merge('GEM_HOME' => autoproj_gem_home),
Gem.ruby, bundler, 'install',
"--gemfile=#{autoproj_gemfile_path}",
"--shebang=#{Gem.ruby}",
"--binstubs=#{binstubs_path}",
*opts, chdir: autoproj_install_dir)
if !result
STDERR.puts "FATAL: failed to install autoproj in #{dot_autoproj}"
exit 1
end
+ ensure
+ self.class.clean_binstubs(binstubs_path)
+ end
+ def self.clean_binstubs(binstubs_path)
+ %w{bundler bundle}.each do |bundler_bin|
+ path = File.join(binstubs_path, bundler_bin)
+ if File.file?(path)
+ FileUtils.rm path
+ end
+ end
+
# Now tune the binstubs to force the usage of the autoproj
# gemfile. Otherwise, they get BUNDLE_GEMFILE from the
# environment by default
Dir.glob(File.join(binstubs_path, '*')) do |path|
next if !File.file?(path)
@@ -284,19 +316,10 @@
end
File.open(path, 'w') do |io|
io.write filtered.join("")
end
end
-
- env['PATH'].unshift File.join(autoproj_install_dir, 'bin')
- if private_autoproj?
- env['GEM_PATH'].unshift autoproj_install_dir
- end
- ensure
- if binstubs_path
- FileUtils.rm_f File.join(binstubs_path, 'bundler')
- end
end
def save_env_sh(*vars)
env = Autobuild::Environment.new
env.prepare
@@ -332,12 +355,12 @@
end
ENV_BUNDLE_GEMFILE_RX = /^(\s*ENV\[['"]BUNDLE_GEMFILE['"]\]\s*)(?:\|\|)?=/
- def find_in_clean_path(command)
- clean_path = env_for_child['PATH'].split(File::PATH_SEPARATOR)
+ def find_in_clean_path(command, *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
@@ -357,25 +380,26 @@
# 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.bindir']).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 private_bundler?
- puts "Installing bundler in #{bundler_install_dir}"
+ puts "Installing bundler in #{bundler_gem_home}"
bundler = install_bundler
- else
- bundler = find_bundler
+ elsif bundler = find_bundler
puts "Detected bundler at #{bundler}"
+ else
+ exit 1
end
save_gemfile
puts "Installing autoproj in #{dot_autoproj}"
install_autoproj(bundler)
end
@@ -389,46 +413,65 @@
end
if File.file?(autoproj_config_path)
config.merge!(YAML.load(File.read(autoproj_config_path)))
end
+ 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"
+ end
+ else
+ config['ruby_executable'] = ruby_executable
+ end
+
@config = config
%w{private_bundler private_gems private_autoproj prefer_indep_over_os_packages}.each do |flag|
instance_variable_set "@#{flag}", config.fetch(flag, false)
end
end
def save_config
- config['private_bundler'] = private_bundler?
- config['private_autoproj'] = private_autoproj?
- config['private_gems'] = private_gems?
+ config['private_bundler'] = (bundler_gem_home if private_bundler?)
+ config['private_autoproj'] = (autoproj_gem_home if private_autoproj?)
+ config['private_gems'] = @private_gems
config['prefer_indep_over_os_packages'] = prefer_indep_over_os_packages?
File.open(autoproj_config_path, 'w') { |io| YAML.dump(config, io) }
end
+ def autoproj_path
+ File.join(autoproj_install_dir, 'bin', 'autoproj')
+ end
+
+ def run_autoproj(*args)
+ system env_for_child.merge('BUNDLE_GEMFILE' => autoproj_gemfile_path),
+ Gem.ruby, autoproj_path, *args
+ end
+
def stage1
FileUtils.mkdir_p dot_autoproj
save_config
install
+ end
+ def call_stage2
clean_env = env_for_child
stage2_vars = clean_env.map { |k, v| "#{k}=#{v}" }
puts "starting the newly installed autoproj for stage2 install"
- result = system clean_env.merge('BUNDLE_GEMFILE' => autoproj_gemfile_path),
- Gem.ruby, File.join(autoproj_install_dir, 'bin', 'autoproj'),
- 'install-stage2', root_dir, *stage2_vars
- if !result
+ if !run_autoproj('install-stage2', root_dir, *stage2_vars)
raise "failed to execute autoproj install-stage2"
end
end
def stage2(*vars)
require 'autobuild'
puts "saving env.sh and .autoproj/env.sh"
save_env_sh(*vars)
puts "calling autoproj envsh"
- system(Gem.ruby, $0, 'envsh')
+ system(Gem.ruby, autoproj_path, 'envsh')
end
end
end
end
@@ -437,5 +480,6 @@
ENV.delete('BUNDLE_GEMFILE')
ENV.delete('RUBYLIB')
ops = Autoproj::Ops::Install.new(Dir.pwd)
ops.parse_options(ARGV)
ops.stage1
+ops.call_stage2