[rubygems/rubygems] Use a constant empty tar header to avoid extra allocations
[ruby.git] / lib / bundler / resolver / base.rb
blobad19eeb3f44992553f8569947d82ca520687ddc1
1 # frozen_string_literal: true
3 require_relative "package"
5 module Bundler
6   class Resolver
7     class Base
8       attr_reader :packages, :requirements, :source_requirements
10       def initialize(source_requirements, dependencies, base, platforms, options)
11         @source_requirements = source_requirements
13         @base = base
15         @packages = Hash.new do |hash, name|
16           hash[name] = Package.new(name, platforms, **options)
17         end
19         @requirements = dependencies.map do |dep|
20           dep_platforms = dep.gem_platforms(platforms)
22           # Dependencies scoped to external platforms are ignored
23           next if dep_platforms.empty?
25           name = dep.name
27           @packages[name] = Package.new(name, dep_platforms, **options.merge(dependency: dep))
29           dep
30         end.compact
31       end
33       def [](name)
34         @base[name]
35       end
37       def delete(specs)
38         @base.delete(specs)
39       end
41       def get_package(name)
42         @packages[name]
43       end
45       def base_requirements
46         @base_requirements ||= build_base_requirements
47       end
49       def unlock_names(names)
50         indirect_pins = indirect_pins(names)
52         if indirect_pins.any?
53           loosen_names(indirect_pins)
54         else
55           pins = pins(names)
57           if pins.any?
58             loosen_names(pins)
59           else
60             unrestrict_names(names)
61           end
62         end
63       end
65       def include_prereleases(names)
66         names.each do |name|
67           get_package(name).consider_prereleases!
68         end
69       end
71       private
73       def indirect_pins(names)
74         names.select {|name| @base_requirements[name].exact? && @requirements.none? {|dep| dep.name == name } }
75       end
77       def pins(names)
78         names.select {|name| @base_requirements[name].exact? }
79       end
81       def loosen_names(names)
82         names.each do |name|
83           version = @base_requirements[name].requirements.first[1]
85           @base_requirements[name] = Gem::Requirement.new(">= #{version}")
87           @base.delete_by_name(name)
88         end
89       end
91       def unrestrict_names(names)
92         names.each do |name|
93           @base_requirements.delete(name)
94         end
95       end
97       def build_base_requirements
98         base_requirements = {}
99         @base.each do |ls|
100           req = Gem::Requirement.new(ls.version)
101           base_requirements[ls.name] = req
102         end
103         base_requirements
104       end
105     end
106   end