diff options
Diffstat (limited to 'lib/rubygems/request_set.rb')
| -rw-r--r-- | lib/rubygems/request_set.rb | 126 |
1 files changed, 87 insertions, 39 deletions
diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb index 01b01599a8..eb8b4658f3 100644 --- a/lib/rubygems/request_set.rb +++ b/lib/rubygems/request_set.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true -require_relative 'tsort' + +require_relative "vendored_tsort" ## # A RequestSet groups a request to activate a set of dependencies. @@ -107,7 +108,7 @@ class Gem::RequestSet @requests = [] @sets = [] @soft_missing = false - @sorted = nil + @sorted_requests = nil @specs = nil @vendor_set = nil @source_set = nil @@ -159,7 +160,7 @@ class Gem::RequestSet end # Create N threads in a pool, have them download all the gems - threads = Gem.configuration.concurrent_downloads.times.map do + threads = Array.new(Gem.configuration.concurrent_downloads) do # When a thread pops this item, it knows to stop running. The symbol # is queued here so that there will be one symbol per thread. download_queue << :stop @@ -180,13 +181,10 @@ class Gem::RequestSet # Install requested gems after they have been downloaded sorted_requests.each do |req| - if req.installed? - req.spec.spec.build_extensions - - if @always_install.none? {|spec| spec == req.spec.spec } - yield req, nil if block_given? - next - end + if req.installed? && @always_install.none? {|spec| spec == req.spec.spec } + req.spec.spec.build_extensions unless options[:build_extension] == false + yield req, nil if block_given? + next end spec = @@ -236,10 +234,6 @@ class Gem::RequestSet sorted_requests.each do |spec| puts " #{spec.full_name}" end - - if Gem.configuration.really_verbose - @resolver.stats.display - end else installed = install options, &block @@ -254,7 +248,8 @@ class Gem::RequestSet end def install_into(dir, force = true, options = {}) - gem_home, ENV['GEM_HOME'] = ENV['GEM_HOME'], dir + gem_home = ENV["GEM_HOME"] + ENV["GEM_HOME"] = dir existing = force ? [] : specs_in(dir) existing.delete_if {|s| @always_install.include? s } @@ -287,7 +282,7 @@ class Gem::RequestSet installed ensure - ENV['GEM_HOME'] = gem_home + ENV["GEM_HOME"] = gem_home end ## @@ -322,12 +317,9 @@ class Gem::RequestSet @git_set.root_dir = @install_dir - lock_file = "#{File.expand_path(path)}.lock".dup.tap(&Gem::UNTAINT) - begin - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file lock_file - parser = tokenizer.make_parser self, [] - parser.parse - rescue Errno::ENOENT + lock_file = "#{File.expand_path(path)}.lock" + if File.exist?(lock_file) + load_lockfile lock_file end gf = Gem::RequestSet::GemDependencyAPI.new self, path @@ -336,33 +328,90 @@ class Gem::RequestSet gf.load end + def load_lockfile(lock_file) # :nodoc: + require "bundler" + require "bundler/lockfile_parser" + + # Bundler::Source::Path resolves relative `remote:` paths against + # Bundler.root, which raises when there is no Gemfile in the working + # directory. Anchor it to the lockfile's directory so PATH sections in a + # `gem install -g` lockfile can be parsed without a Bundler environment. + previous_root = Bundler.instance_variable_get(:@root) + Bundler.instance_variable_set(:@root, Pathname.new(File.expand_path(File.dirname(lock_file)))) + + parser = Bundler::LockfileParser.new(File.read(lock_file), lockfile_path: lock_file) + + parser.specs.group_by(&:source).each do |source, specs| + case source + when Bundler::Source::Rubygems + remotes = source.remotes.map {|remote| Gem::Source.new(remote.to_s) } + remotes << Gem::Source.new(Gem::DEFAULT_HOST) if remotes.empty? + lock_set = Gem::Resolver::LockSet.new(remotes) + specs.each do |spec| + added = lock_set.add(spec.name, spec.version.to_s, spec.platform) + spec.dependencies.each do |dep| + added.each {|s| s.add_dependency dep } + end + end + @sets << lock_set + when Bundler::Source::Git + git_set = Gem::Resolver::GitSet.new + git_set.root_dir = @install_dir + specs.each do |spec| + git_spec = git_set.add_git_spec( + spec.name, + spec.version.to_s, + source.uri.to_s, + source.revision, + source.submodules || false + ) + spec.dependencies.each {|dep| git_spec.add_dependency dep } + end + @sets << git_set + when Bundler::Source::Path + vendor_set = Gem::Resolver::VendorSet.new + specs.each do |spec| + loaded = vendor_set.add_vendor_gem(spec.name, source.path.to_s) + spec.dependencies.each {|dep| loaded.dependencies << dep } + end + @sets << vendor_set + end + end + + parser.dependencies.each_value do |dep| + gem dep.name, *dep.requirement.as_list + end + ensure + Bundler.instance_variable_set(:@root, previous_root) if defined?(previous_root) + end + def pretty_print(q) # :nodoc: - q.group 2, '[RequestSet:', ']' do + q.group 2, "[RequestSet:", "]" do q.breakable if @remote - q.text 'remote' + q.text "remote" q.breakable end if @prerelease - q.text 'prerelease' + q.text "prerelease" q.breakable end if @development_shallow - q.text 'shallow development' + q.text "shallow development" q.breakable elsif @development - q.text 'development' + q.text "development" q.breakable end if @soft_missing - q.text 'soft missing' + q.text "soft missing" end - q.group 2, '[dependencies:', ']' do + q.group 2, "[dependencies:", "]" do q.breakable @dependencies.map do |dep| q.text dep.to_s @@ -371,10 +420,10 @@ class Gem::RequestSet end q.breakable - q.text 'sets:' + q.text "sets:" q.breakable - q.pp @sets.map {|set| set.class } + q.pp @sets.map(&:class) end end @@ -424,11 +473,11 @@ class Gem::RequestSet end def sorted_requests - @sorted ||= strongly_connected_components.flatten + @sorted_requests ||= strongly_connected_components.flatten end def specs - @specs ||= @requests.map {|r| r.full_spec } + @specs ||= @requests.map(&:full_spec) end def specs_in(dir) @@ -443,14 +492,14 @@ class Gem::RequestSet def tsort_each_child(node) # :nodoc: node.spec.dependencies.each do |dep| - next if dep.type == :development and not @development + next if dep.type == :development && !@development match = @requests.find do |r| - dep.match? r.spec.name, r.spec.version, @prerelease + dep.match?(r.spec.name, r.spec.version, r.spec.is_a?(Gem::Resolver::InstalledSpecification) || @prerelease) end unless match - next if dep.type == :development and @development_shallow + next if dep.type == :development && @development_shallow next if @soft_missing raise Gem::DependencyError, "Unresolved dependency found during sorting - #{dep} (requested by #{node.spec.full_name})" @@ -461,6 +510,5 @@ class Gem::RequestSet end end -require_relative 'request_set/gem_dependency_api' -require_relative 'request_set/lockfile' -require_relative 'request_set/lockfile/tokenizer' +require_relative "request_set/gem_dependency_api" +require_relative "request_set/lockfile" |
