bin/autoproj_bootstrap in autoproj-2.0.0.rc5 vs bin/autoproj_bootstrap in autoproj-2.0.0.rc6
- old
+ new
@@ -24,22 +24,22 @@
attr_reader :root_dir
# Content of the Gemfile generated to install autoproj itself
attr_accessor :gemfile
# The environment that is passed to the bundler installs
attr_reader :env
+ # The configuration hash
+ attr_reader :config
def initialize(root_dir)
@root_dir = root_dir
if File.file?(autoproj_gemfile_path)
@gemfile = File.read(autoproj_gemfile_path)
else
@gemfile = default_gemfile_contents
end
- @private_bundler = false
- @private_autoproj = false
- @private_gems = false
+ load_config
@local = false
@env = self.class.clean_env
end
def self.clean_env
@@ -47,21 +47,31 @@
env['RUBYLIB'] = []
env['GEM_PATH'] = []
%w{PATH GEM_HOME}.each do |name|
env[name] = sanitize_env(ENV[name] || "")
end
- env['BUNDLE_GEMFILE'] = nil
+ env['BUNDLE_GEMFILE'] = []
env
end
def env_for_child
env.inject(Hash.new) do |h, (k, v)|
h[k] = (v.join(File::PATH_SEPARATOR) if v && !v.empty?)
h
end
end
+ def apply_env(env)
+ env.each do |k, v|
+ if v
+ ENV[k] = v
+ else
+ ENV.delete(k)
+ end
+ end
+ end
+
def self.sanitize_env(value)
value.split(File::PATH_SEPARATOR).
find_all { |p| !in_workspace?(p) }
end
@@ -76,11 +86,10 @@
return false
end
def dot_autoproj; File.join(root_dir, '.autoproj') end
- def bin_dir; File.join(dot_autoproj, 'bin') 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
@@ -91,20 +100,26 @@
def local=(flag); @local = flag end
# Whether bundler should be installed locally in {#dot_autoproj}
def private_bundler?; @private_bundler end
# (see #private_bundler?)
- def private_bundler=(flag); @private_bundler = flag end
+ def private_bundler=(flag); @private_bundler = !!flag end
# Whether autoproj should be installed locally in {#dot_autoproj}
def private_autoproj?; @private_autoproj end
# (see #private_autoproj?)
- def private_autoproj=(flag); @private_autoproj = flag end
+ 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
# (see #private_gems?)
- def private_gems=(flag); @private_gems = flag end
+ def private_gems=(flag); @private_gems = !!flag 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?)
+ def prefer_indep_over_os_packages=(flag); @prefer_indep_over_os_packages = !!flag end
def guess_gem_program
ruby_bin = RbConfig::CONFIG['RUBY_INSTALL_NAME']
ruby_bindir = RbConfig::CONFIG['bindir']
@@ -156,10 +171,13 @@
@gemfile = default_gemfile_contents(version)
end
opt.on '--gemfile=PATH', String, 'use the given Gemfile to install autoproj instead of the default' do |path|
@gemfile = 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
+ @prefer_indep_over_os_packages = true
+ end
end
options.parse(ARGV)
end
def install_bundler
@@ -176,95 +194,86 @@
if !result
STDERR.puts "FATAL: failed to install bundler in #{dot_autoproj}"
exit 1
end
- env['GEM_PATH'] << bundler_install_dir
- env['PATH'] << File.join(bundler_install_dir, 'bin')
- File.join(bin_dir, 'bundler')
+ env['PATH'].unshift File.join(bundler_install_dir, 'bin')
+ File.join(bundler_install_dir, 'bin', 'bundler')
end
- def save_env_sh
- env = Autobuild::Environment.new
- env.prepare
+ 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
+ ]
- %w{GEM_HOME GEM_PATH}.each do |name|
- value = self.env[name]
- if value.empty?
- env.unset name
- else
- env.set name, *value
+ 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
- end
- env.push_path 'PATH', File.join(autoproj_install_dir, 'bin')
- if private_autoproj?
- env.push_path 'GEM_PATH', autoproj_install_dir
+ 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}"
+ end
end
- # Generate environment files right now, we can at least use bundler
- File.open(File.join(dot_autoproj, 'env.sh'), 'w') do |io|
- env.export_env_sh(io)
- end
-
- File.open(File.join(root_dir, 'env.sh'), 'w') do |io|
- io.write <<-EOSHELL
-source "#{File.join(dot_autoproj, 'env.sh')}"
-export AUTOPROJ_CURRENT_ROOT=#{root_dir}
- EOSHELL
- end
+ bundler
end
- def save_gemfile
- FileUtils.mkdir_p File.dirname(autoproj_gemfile_path)
- File.open(autoproj_gemfile_path, 'w') do |io|
- io.write gemfile
- end
- end
-
- ENV_BUNDLE_GEMFILE_RX = /^(\s*ENV\[['"]BUNDLE_GEMFILE['"]\]\s*)(?:\|\|)?=/
-
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(File.dirname(autoproj_gemfile_path), 'Gemfile.lock')
+ lockfile = File.join(File.dirname(autoproj_install_dir), 'Gemfile.lock')
if File.exist?(lockfile)
FileUtils.rm lockfile
end
opts = Array.new
- opts << '--local' if local?
+ clean_env = env_for_child.merge('BUNDLE_GEMFILE' => nil)
- env = env_for_child
+ opts << '--local' if local?
if private_autoproj?
- env = env.merge(
- 'GEM_PATH' => bundler_install_dir,
- 'GEM_HOME' => nil)
+ clean_env['GEM_PATH'] = (bundler_install_dir if private_bundler?)
+ clean_env['GEM_HOME'] = nil
opts << "--clean" << "--path=#{autoproj_install_dir}"
end
-
binstubs_path = File.join(autoproj_install_dir, 'bin')
-
- result = system(env,
+ result = system(clean_env,
Gem.ruby, bundler, 'install',
"--gemfile=#{autoproj_gemfile_path}",
+ "--shebang=#{Gem.ruby}",
"--binstubs=#{binstubs_path}",
- *opts)
+ *opts, chdir: autoproj_install_dir)
+
if !result
STDERR.puts "FATAL: failed to install autoproj in #{dot_autoproj}"
exit 1
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)
- # Do NOT do that for bundler, otherwise it will fail with an
- # "already loaded gemfile" message once we e.g. try to do
- # 'bundler install --gemfile=NEW_GEMFILE'
- next if File.basename(path) == 'bundler'
lines = File.readlines(path)
matched = false
filtered = lines.map do |l|
matched ||= (ENV_BUNDLE_GEMFILE_RX === l)
@@ -276,30 +285,57 @@
File.open(path, 'w') do |io|
io.write filtered.join("")
end
end
- env['PATH'] << File.join(autoproj_install_dir, 'bin')
+ env['PATH'].unshift File.join(autoproj_install_dir, 'bin')
if private_autoproj?
- env['GEM_PATH'] << autoproj_install_dir
+ env['GEM_PATH'].unshift autoproj_install_dir
end
+ ensure
+ if binstubs_path
+ FileUtils.rm_f File.join(binstubs_path, 'bundler')
+ end
end
- def update_configuration
- if File.exist?(autoproj_config_path)
- config = YAML.load(File.read(autoproj_config_path)) || Hash.new
- else
- config = Hash.new
+ def save_env_sh(*vars)
+ env = Autobuild::Environment.new
+ env.prepare
+ vars.each do |kv|
+ k, *v = kv.split("=")
+ v = v.join("=")
+
+ if v.empty?
+ env.unset k
+ else
+ env.set k, *v.split(File::PATH_SEPARATOR)
+ end
end
- config['private_bundler'] = private_bundler?
- config['private_autoproj'] = private_autoproj?
- config['private_gems'] = private_gems?
- File.open(autoproj_config_path, 'w') do |io|
- YAML.dump(config, io)
+ # Generate environment files right now, we can at least use bundler
+ File.open(File.join(dot_autoproj, 'env.sh'), 'w') do |io|
+ env.export_env_sh(io)
end
+
+ # And now the root envsh
+ env = Autobuild::Environment.new
+ env.source_before File.join(dot_autoproj, 'env.sh')
+ env.set('AUTOPROJ_CURRENT_ROOT', root_dir)
+ File.open(File.join(root_dir, 'env.sh'), 'w') do |io|
+ env.export_env_sh(io)
+ end
end
+ def save_gemfile
+ FileUtils.mkdir_p File.dirname(autoproj_gemfile_path)
+ File.open(autoproj_gemfile_path, 'w') do |io|
+ io.write gemfile
+ end
+ 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)
clean_path.each do |p|
full_path = File.join(p, command)
if File.file?(full_path)
@@ -307,50 +343,30 @@
end
end
nil
end
- def find_bundler
- clean_env = env_for_child
- Gem.paths = Hash[
- 'GEM_HOME' => clean_env['GEM_HOME'] || Gem.default_dir,
- 'GEM_PATH' => clean_env['GEM_PATH'] || nil
- ]
+ # The path of the bin/ folder for installed gems
+ def gem_bindir
+ return @gem_bindir if @gem_bindir
+
# Here, we're getting into the esotheric
#
# The problem is that e.g. Ubuntu and Debian install an
# operating_system.rb file that sets proper OS defaults. Some
# autoproj installs have it in their RUBYLIB but should not
# 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(clean_env, [Gem.ruby, '-e', 'puts Gem.bindir']).read
+ bindir = IO.popen(env_for_child, [Gem.ruby, '-e', 'puts Gem.bindir']).read
if bindir
- env['PATH'].unshift bindir.chomp
+ @gem_bindir = bindir.chomp
else
- STDERR.puts "FATAL: cannot run #{Gem.ruby} -e 'puts Gem.bindir'"
- exit 1
+ raise "FATAL: cannot run #{Gem.ruby} -e 'puts Gem.bindir'"
end
-
- bundler = find_in_clean_path('bundler')
- if !bundler
- clean_path = env_for_child['PATH']
- STDERR.puts "FATAL: cannot find 'bundler' in PATH=#{clean_path}"
- 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
end
def install
if private_bundler?
puts "Installing bundler in #{bundler_install_dir}"
@@ -362,29 +378,56 @@
save_gemfile
puts "Installing autoproj in #{dot_autoproj}"
install_autoproj(bundler)
end
- # Actually perform the install
- def run(stage2: false)
- if stage2
- require 'autobuild'
- save_env_sh
- else
- install
+ 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)))
+ end
+ if File.file?(autoproj_config_path)
+ config.merge!(YAML.load(File.read(autoproj_config_path)))
+ end
- env_for_child.each do |k, v|
- if v
- ENV[k] = v
- else
- ENV.delete(k)
- end
- end
- ENV['BUNDLE_GEMFILE'] = autoproj_gemfile_path
- update_configuration
- exec Gem.ruby, File.join(autoproj_install_dir, 'bin', 'autoproj'),
- 'install-stage2', root_dir
+ @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['prefer_indep_over_os_packages'] = prefer_indep_over_os_packages?
+ File.open(autoproj_config_path, 'w') { |io| YAML.dump(config, io) }
+ end
+
+ def stage1
+ FileUtils.mkdir_p dot_autoproj
+ save_config
+ install
+
+ clean_env = env_for_child
+ stage2_vars = clean_env.map { |k, v| "#{k}=#{v}" }
+ puts "starting the newly installed autoproj for stage2 install"
+ puts [clean_env.merge('BUNDLE_GEMFILE' => autoproj_gemfile_path),
+ Gem.ruby, File.join(autoproj_install_dir, 'bin', 'autoproj'),
+ 'install-stage2', root_dir, *stage2_vars].inspect
+ exec clean_env.merge('BUNDLE_GEMFILE' => autoproj_gemfile_path),
+ Gem.ruby, File.join(autoproj_install_dir, 'bin', 'autoproj'),
+ 'install-stage2', root_dir, *stage2_vars
+ 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')
end
end
end
end