1# frozen_string_literal: true 2 3require "rubygems/util" 4 5module Gem::BundlerVersionFinder 6 def self.bundler_version 7 version, _ = bundler_version_with_reason 8 9 return unless version 10 11 Gem::Version.new(version) 12 end 13 14 def self.bundler_version_with_reason 15 if v = ENV["BUNDLER_VERSION"] 16 return [v, "`$BUNDLER_VERSION`"] 17 end 18 if v = bundle_update_bundler_version 19 return if v == true 20 return [v, "`bundle update --bundler`"] 21 end 22 v, lockfile = lockfile_version 23 if v 24 return [v, "your #{lockfile}"] 25 end 26 end 27 28 def self.missing_version_message 29 return unless vr = bundler_version_with_reason 30 <<-EOS 31Could not find 'bundler' (#{vr.first}) required by #{vr.last}. 32To update to the latest version installed on your system, run `bundle update --bundler`. 33To install the missing version, run `gem install bundler:#{vr.first}` 34 EOS 35 end 36 37 def self.compatible?(spec) 38 return true unless spec.name == "bundler".freeze 39 return true unless bundler_version = self.bundler_version 40 41 spec.version.segments.first == bundler_version.segments.first 42 end 43 44 def self.filter!(specs) 45 return unless bundler_version = self.bundler_version 46 47 specs.reject! { |spec| spec.version.segments.first != bundler_version.segments.first } 48 end 49 50 def self.bundle_update_bundler_version 51 return unless File.basename($0) == "bundle".freeze 52 return unless "update".start_with?(ARGV.first || " ") 53 bundler_version = nil 54 update_index = nil 55 ARGV.each_with_index do |a, i| 56 if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN 57 bundler_version = a 58 end 59 next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ 60 bundler_version = $1 || true 61 update_index = i 62 end 63 bundler_version 64 end 65 private_class_method :bundle_update_bundler_version 66 67 def self.lockfile_version 68 return unless lockfile = lockfile_contents 69 lockfile, contents = lockfile 70 lockfile ||= "lockfile" 71 regexp = /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ 72 return unless contents =~ regexp 73 [$1, lockfile] 74 end 75 private_class_method :lockfile_version 76 77 def self.lockfile_contents 78 gemfile = ENV["BUNDLE_GEMFILE"] 79 gemfile = nil if gemfile && gemfile.empty? 80 Gem::Util.traverse_parents Dir.pwd do |directory| 81 next unless gemfile = Gem::GEM_DEP_FILES.find { |f| File.file?(f.untaint) } 82 83 gemfile = File.join directory, gemfile 84 break 85 end unless gemfile 86 87 return unless gemfile 88 89 lockfile = case gemfile 90 when "gems.rb" then "gems.locked" 91 else "#{gemfile}.lock" 92 end.dup.untaint 93 94 return unless File.file?(lockfile) 95 96 [lockfile, File.read(lockfile)] 97 end 98 private_class_method :lockfile_contents 99end 100