class TargetBundle
Attributes
Public Class Methods
# File lib/bundler/patch/target_bundle.rb, line 4 def self.bundler_version_or_higher(version) version_greater_than_or_equal_to_other(Bundler::VERSION, version) end
# File lib/bundler/patch/target_bundle.rb, line 12 def self.default_gemfile # TODO: Make gems.rb default in Bundler 2.0. 'Gemfile' end
# File lib/bundler/patch/target_bundle.rb, line 17 def initialize(dir: Dir.pwd, gemfile: TargetBundle.default_gemfile) @dir = dir @gemfile = gemfile end
# File lib/bundler/patch/target_bundle.rb, line 8 def self.version_greater_than_or_equal_to_other(a, b) Gem::Version.new(a) >= Gem::Version.new(b) end
Public Instance Methods
# File lib/bundler/patch/target_bundle.rb, line 62 def build_ruby_bin(current_ruby_bin, target_ruby_version) current_ruby_bin.split(File::SEPARATOR).reverse.map do |segment| if segment =~ /\d+\.\d+\.\d+/ segment.gsub(/(\d+\.\d+\.\d+)-*(p\d+)*/, target_ruby_version) else segment end end.reverse.join(File::SEPARATOR) end
Have to run a separate process in the other Ruby, because Gem.default_dir depends on RbConfig::CONFIG which is all special data derived from the active runtime. It could perhaps be redone here, but I'd rather not copy that code in here at the moment.
At one point during development, this would execute Bundler::Settings#path, which in most cases would just fall through to Gem.default_dir … but would give preference to GEM_HOME env variable, which could be in a different Ruby, and that won't work.
# File lib/bundler/patch/target_bundle.rb, line 89 def gem_home result = shell_command "#{ruby_bin_exe} -C#{@dir} -e 'puts Gem.default_dir'" path = result[:stdout].chomp expanded_path = Pathname.new(path).expand_path(@dir).to_s puts expanded_path if ENV['BP_DEBUG'] expanded_path end
To properly update another bundle, bundler-patch does need to live in the same Ruby version because of its dependencies (it's not a self-contained gem), and it can't both act on another bundle location AND find its own dependencies in a separate bundle location.
One known issue: older RubyGems in older Rubies don't install bundler-patch bin in the right directory. Upgrading RubyGems fixes this.
# File lib/bundler/patch/target_bundle.rb, line 103 def install_bundler_patch_in_target # TODO: reconsider --conservative flag. Had problems with it in place on Travis, but I think I want it. # cmd = "#{ruby_bin}#{File::SEPARATOR}gem install -V --install-dir #{gem_home} --conservative --no-document --prerelease bundler-patch" cmd = "#{ruby_bin}#{File::SEPARATOR}gem install -V --install-dir #{gem_home} --no-document --prerelease bundler-patch" shell_command cmd end
This is hairy here. All the possible variants will make this mucky, but … can prolly get close enough in many circumstances.
# File lib/bundler/patch/target_bundle.rb, line 48 def ruby_bin(current_ruby_bin=RbConfig::CONFIG['bindir'], target_ruby_version=self.ruby_version) [ target_ruby_version, target_ruby_version.gsub(/-p\d+/, ''), "ruby-#{target_ruby_version}", "ruby-#{target_ruby_version.gsub(/-p\d+/, '')}" ].map do |ruby_ver| build_ruby_bin(current_ruby_bin, ruby_ver) end.detect do |ruby_ver| print "Looking for #{ruby_ver}... " if ENV['BP_DEBUG'] File.exist?(ruby_ver).tap { |exist| puts(exist ? 'found' : 'not found') if ENV['BP_DEBUG'] } end end
# File lib/bundler/patch/target_bundle.rb, line 72 def ruby_bin_exe ruby_install_name = RbConfig::CONFIG['ruby_install_name'] exe_ext = RbConfig::CONFIG['EXEEXT'] File.join(ruby_bin, "#{ruby_install_name}#{exe_ext}") end
First, the version of Ruby itself:
-
Look in the Gemfile/lockfile for ruby version
-
Look for a .ruby-version file
-
(An additional flag so user can specify?)
Second, look bin path presuming version is in current path.
# File lib/bundler/patch/target_bundle.rb, line 28 def ruby_version result = if TargetBundle.bundler_version_or_higher('1.12.0') && File.exist?(lockfile_name) lockfile_parser = Bundler::LockfileParser.new(Bundler.read_file(lockfile_name)) lockfile_parser.ruby_version end result ||= if File.exist?(ruby_version_filename) File.read(File.join(@dir, '.ruby-version')).chomp elsif File.exist?(gemfile_name) Bundler::Definition.build(gemfile_name, lockfile_name, nil).ruby_version end result ||= RbConfig::CONFIG['RUBY_PROGRAM_VERSION'] version, patch_level = result.to_s.scan(/(\d+\.\d+\.\d+)(p\d+)*/).first patch_level ? "#{version}-#{patch_level}" : version end
# File lib/bundler/patch/target_bundle.rb, line 78 def target_ruby_is_different? !(ruby_bin == RbConfig::CONFIG['bindir']) end
Private Instance Methods
# File lib/bundler/patch/target_bundle.rb, line 116 def gemfile_name File.join(@dir, @gemfile) end
# File lib/bundler/patch/target_bundle.rb, line 120 def lockfile_name "#{gemfile_name}.lock" end
# File lib/bundler/patch/target_bundle.rb, line 112 def ruby_version_filename File.join(@dir, '.ruby-version') end