lib/autoproj/package_managers/bundler_manager.rb in autoproj-2.0.0.rc15 vs lib/autoproj/package_managers/bundler_manager.rb in autoproj-2.0.0.rc16
- old
+ new
@@ -29,30 +29,29 @@
def initialize_environment
env = ws.env
config = ws.config
- env.add_path 'PATH', File.join(Gem.user_dir, 'bin')
env.add_path 'PATH', File.join(ws.prefix_dir, 'gems', 'bin')
env.add_path 'PATH', File.join(config.bundler_gem_home, 'bin')
env.add_path 'PATH', File.join(ws.dot_autoproj_dir, 'autoproj', 'bin')
env.set 'GEM_HOME', config.gems_gem_home
+ env.set 'GEM_PATH', config.bundler_gem_home
root_dir = File.join(ws.prefix_dir, 'gems')
gemfile_path = File.join(root_dir, 'Gemfile')
if File.file?(gemfile_path)
env.set('BUNDLE_GEMFILE', gemfile_path)
end
if !config.private_bundler? || !config.private_autoproj? || !config.private_gems?
env.set('GEM_PATH', *Gem.default_path)
end
+ Autobuild.programs['bundler'] = File.join(ws.dot_autoproj_dir, 'bin', 'bundler')
+
if config.private_bundler?
- Autobuild.programs['bundler'] = File.join(config.bundler_gem_home, 'bin', 'bundler')
env.add_path 'GEM_PATH', config.bundler_gem_home
- else
- Autobuild.programs['bundler'] = env.find_in_path('bundler')
end
env.init_from_env 'RUBYLIB'
env.inherit 'RUBYLIB'
# Sanitize the rubylib we get from the environment by removing
@@ -62,10 +61,15 @@
!p.start_with?(Bundler.rubygems.gem_dir) &&
!Bundler.rubygems.gem_path.any? { |gem_p| p.start_with?(p) }
end
# And discover the system's rubylib
if system_rubylib = discover_rubylib
+ # Do not explicitely add the system rubylib to the
+ # environment, the interpreter will do it for us.
+ #
+ # This allows to use a binstub generated for one of ruby
+ # interpreter version on our workspace
env.system_env['RUBYLIB'] = []
env.original_env['RUBYLIB'] = (original_rubylib - system_rubylib).join(File::PATH_SEPARATOR)
end
ws.config.each_reused_autoproj_installation do |p|
@@ -158,10 +162,67 @@
end
end
end
end
+ # Parse the contents of a gemfile into a set of
+ def merge_gemfiles(*path, unlock: [])
+ gems_remotes = Set.new
+ dependencies = Hash.new do |h, k|
+ h[k] = Hash.new do |h, k|
+ h[k] = Hash.new do |a, b|
+ a[b] = Array.new
+ end
+ end
+ end
+ path.each do |gemfile|
+ bundler_def = Bundler::Dsl.evaluate(gemfile, nil, [])
+ gems_remotes |= bundler_def.send(:sources).rubygems_remotes.to_set
+ bundler_def.dependencies.each do |d|
+ d.groups.each do |group_name|
+ if !d.platforms.empty?
+ d.platforms.each do |platform_name|
+ dependencies[group_name][platform_name][d.name] = d
+ end
+ else
+ dependencies[group_name][''][d.name] = d
+ end
+ end
+ end
+ end
+
+ contents = []
+ gems_remotes.each do |g|
+ g = g.to_s
+ if g.end_with?('/')
+ g = g[0..-2]
+ end
+ contents << "source '#{g.to_s}'"
+ end
+ dependencies.each do |group_name, by_platform|
+ contents << "group :#{group_name} do"
+ by_platform.each do |platform_name, deps|
+ deps = deps.values.sort_by(&:name)
+ if !platform_name.empty?
+ contents << " platform :#{platform_name} do"
+ platform_indent = " "
+ end
+ deps.each do |d|
+ if d.source
+ options = d.source.options.map { |k, v| "#{k}: \"#{v}\"" }
+ end
+ contents << [" #{platform_indent}gem \"#{d.name}\", \"#{d.requirement}\"", *options].join(", ")
+ end
+ if !platform_name.empty?
+ contents << " end"
+ end
+ end
+ contents << "end"
+ end
+ contents.join("\n")
+ end
+
def install(gems, filter_uptodate_packages: false, install_only: false)
root_dir = File.join(ws.prefix_dir, 'gems')
gemfile_path = File.join(root_dir, 'Gemfile')
gemfile_lock_path = "#{gemfile_path}.lock"
backups = Hash[
@@ -186,35 +247,36 @@
end
# In addition, look into overrides.d
Dir.glob(File.join(ws.overrides_dir, "*.gemfile")) do |gemfile_path|
gemfiles << gemfile_path
end
+ gemfiles << File.join(ws.dot_autoproj_dir, 'autoproj', 'Gemfile')
- # Generate the gemfile and remove the lockfile
- gemfile_lines = gems.map do |name|
- name, version = parse_package_entry(name)
- "gem \"#{name}\", \"#{version || ">= 0"}\""
+ # Save the osdeps entries in a temporary gemfile and finally
+ # merge the whole lot of it
+ gemfile_contents = Tempfile.open 'autoproj-gemfile' do |io|
+ osdeps_gemfile_lines = gems.sort.map do |name|
+ name, version = parse_package_entry(name)
+ io.puts "gem \"#{name}\", \"#{version || ">= 0"}\""
+ end
+ io.flush
+ gemfiles.unshift io.path
+ # The autoproj gemfile needs to be last, we really don't
+ # want to mess it up
+ merge_gemfiles(*gemfiles)
end
- gemfiles.each do |gemfile|
- gemfile_lines.concat(File.readlines(gemfile).map(&:chomp))
- end
- gemfile_lines = gemfile_lines.sort.uniq
- gemfile_contents = [
- "eval_gemfile \"#{File.join(ws.dot_autoproj_dir, 'autoproj', 'Gemfile')}\"",
- *gemfile_lines
- ].join("\n")
FileUtils.mkdir_p root_dir
if updated = (!File.exist?(gemfile_path) || File.read(gemfile_path) != gemfile_contents)
File.open(gemfile_path, 'w') do |io|
io.puts gemfile_contents
end
end
options = Array.new
if ws.config.private_gems?
- options << "--path" << ws.config.gems_gem_home
+ options << "--path" << ws.config.gems_bundler_path
end
binstubs_path = File.join(root_dir, 'bin')
if updated || !install_only || !File.file?("#{gemfile_path}.lock")
self.class.run_bundler_install ws, gemfile_path, *options,
@@ -231,11 +293,11 @@
Autoproj.warn "saved the new Gemfile in #{gemfile_path}.FAILED and restored the last Gemfile version"
FileUtils.cp gemfile_path, "#{gemfile_path}.FAILED"
backup_restore(backups)
raise
ensure
- FileUtils.rm_f File.join(binstubs_path, 'bundler')
+ FileUtils.rm_f File.join(binstubs_path, 'bundler') if binstubs_path
backup_clean(backups)
end
def discover_rubylib
require 'bundler'
@@ -244,10 +306,11 @@
Hash['RUBYLIB' => nil],
Autobuild.tool('ruby'), '-e', 'puts $LOAD_PATH',
out: io,
err: '/dev/null')
if result
+ io.rewind
io.readlines.map { |l| l.chomp }.find_all { |l| !l.empty? }
end
end
end
@@ -258,14 +321,15 @@
if silent_errors
silent_redirect[:err] = '/dev/null'
end
Tempfile.open 'autoproj-rubylib' do |io|
result = Bundler.clean_system(
- Hash['BUNDLE_GEMFILE' => gemfile],
- Autobuild.tool('bundler'), 'exec', 'ruby', '-e', 'puts $LOAD_PATH',
+ Hash['BUNDLE_GEMFILE' => gemfile, 'RUBYLIB' => nil],
+ Autobuild.tool('bundler'), 'exec', Autobuild.tool('ruby'), '-rbundler/setup', '-e', 'puts $LOAD_PATH',
out: io, **silent_redirect)
if result
+ io.rewind
io.readlines.map { |l| l.chomp }.find_all { |l| !l.empty? }
end
end
end
end