# class Gem::SpecificationRecord

### Constants

NOT_FOUND

  Sentinel object to represent “not found” stubs

### Public Class Methods

dirs_from(paths) click to toggle source

    # File lib/rubygems/specification_record.rb, line 5
    def self.dirs_from(paths)
      paths.map do |path|
        File.join(path, "specifications")
      end
    end

from_path(path) click to toggle source

    # File lib/rubygems/specification_record.rb, line 11
    def self.from_path(path)
      new(dirs_from([path]))
    end

new(dirs) click to toggle source

    # File lib/rubygems/specification_record.rb, line 15
    def initialize(dirs)
      @all = nil
      @stubs = nil
      @stubs_by_name = {}
      @spec_with_requirable_file = {}
      @active_stub_with_requirable_file = {}

      @dirs = dirs
    end

### Public Instance Methods

add_spec(spec) click to toggle source

Adds `spec` to the the record, keeping the collection properly sorted.

    # File lib/rubygems/specification_record.rb, line 78
    def add_spec(spec)
      return if all.include? spec

      all << spec
      stubs << spec
      (@stubs_by_name[spec.name] ||= []) << spec

      Gem::Specification._resort!(@stubs_by_name[spec.name])
      Gem::Specification._resort!(stubs)
    end

all() click to toggle source

Returns the list of all specifications in the record

    # File lib/rubygems/specification_record.rb, line 32
    def all
      @all ||= stubs.map(&:to_spec)
    end

all=(specs) click to toggle source

Sets the specs known by the record to `specs`.

    # File lib/rubygems/specification_record.rb, line 101
    def all=(specs)
      @stubs_by_name = specs.group_by(&:name)
      @all = @stubs = specs
    end

all_names() click to toggle source

Return full names of all specs in the record in sorted order.

    # File lib/rubygems/specification_record.rb, line 109
    def all_names
      all.map(&:full_name)
    end

each() { |x| ... } click to toggle source

Enumerate every known spec.

    # File lib/rubygems/specification_record.rb, line 118
    def each
      return enum_for(:each) unless block_given?

      all.each do |x|
        yield x
      end
    end

find_active_stub_by_path(path) click to toggle source

Return the best specification in the record that contains the file matching `path`, among those already activated.

    # File lib/rubygems/specification_record.rb, line 173
    def find_active_stub_by_path(path)
      stub = @active_stub_with_requirable_file[path] ||= stubs.find do |s|
        s.activated? && s.contains_requirable_file?(path)
      end || NOT_FOUND

      stub.this
    end

find_all_by_name(name, *requirements) click to toggle source

Returns every spec in the record that matches `name` and optional `requirements`.

    # File lib/rubygems/specification_record.rb, line 129
    def find_all_by_name(name, *requirements)
      req = Gem::Requirement.create(*requirements)
      env_req = Gem.env_requirement(name)

      matches = stubs_for(name).find_all do |spec|
        req.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version)
      end.map(&:to_spec)

      if name == "bundler" && !req.specific?
        require_relative "bundler_version_finder"
        Gem::BundlerVersionFinder.prioritize!(matches)
      end

      matches
    end

find_by_path(path) click to toggle source

Return the best specification in the record that contains the file matching `path`.

    # File lib/rubygems/specification_record.rb, line 148
    def find_by_path(path)
      path = path.dup.freeze
      spec = @spec_with_requirable_file[path] ||= stubs.find do |s|
        s.contains_requirable_file? path
      end || NOT_FOUND

      spec.to_spec
    end

find_inactive_by_path(path) click to toggle source

Return the best specification in the record that contains the file matching `path` amongst the specs that are not activated.

    # File lib/rubygems/specification_record.rb, line 161
    def find_inactive_by_path(path)
      stub = stubs.find do |s|
        next if s.activated?
        s.contains_requirable_file? path
      end
      stub&.to_spec
    end

latest_spec_for(name) click to toggle source

Return the latest installed spec in the record for gem `name`.

    # File lib/rubygems/specification_record.rb, line 192
    def latest_spec_for(name)
      latest_specs(true).find {|installed_spec| installed_spec.name == name }
    end

latest_specs(prerelease) click to toggle source

Return the latest specs in the record, optionally including prerelease specs if `prerelease` is true.

    # File lib/rubygems/specification_record.rb, line 185
    def latest_specs(prerelease)
      Gem::Specification._latest_specs stubs, prerelease
    end

remove_spec(spec) click to toggle source

Removes `spec` from the record.

    # File lib/rubygems/specification_record.rb, line 92
    def remove_spec(spec)
      all.delete spec.to_spec
      stubs.delete spec
      (@stubs_by_name[spec.name] || []).delete spec
    end

stubs() click to toggle source

Returns a `Gem::StubSpecification` for every specification in the record

    # File lib/rubygems/specification_record.rb, line 39
    def stubs
      @stubs ||= begin
        pattern = "*.gemspec"
        stubs = stubs_for_pattern(pattern, false)

        @stubs_by_name = stubs.select {|s| Gem::Platform.match_spec? s }.group_by(&:name)
        stubs
      end
    end

stubs_for(name) click to toggle source

Returns a `Gem::StubSpecification` for every specification in the record named `name` only returns stubs that match `Gem.platforms`

    # File lib/rubygems/specification_record.rb, line 53
    def stubs_for(name)
      if @stubs
        @stubs_by_name[name] || []
      else
        @stubs_by_name[name] ||= stubs_for_pattern("#{name}-*.gemspec").select do |s|
          s.name == name
        end
      end
    end

stubs_for_pattern(pattern, match_platform = true) click to toggle source

Finds stub specifications matching a pattern in the record, optionally filtering out specs not matching the current platform

    # File lib/rubygems/specification_record.rb, line 67
    def stubs_for_pattern(pattern, match_platform = true)
      installed_stubs = installed_stubs(pattern)
      installed_stubs.select! {|s| Gem::Platform.match_spec? s } if match_platform
      stubs = installed_stubs + Gem::Specification.default_stubs(pattern)
      Gem::Specification._resort!(stubs)
      stubs
    end

### Private Instance Methods

installed_stubs(pattern) click to toggle source

    # File lib/rubygems/specification_record.rb, line 198
    def installed_stubs(pattern)
      map_stubs(pattern) do |path, base_dir, gems_dir|
        Gem::StubSpecification.gemspec_stub(path, base_dir, gems_dir)
      end
    end

map_stubs(pattern) { |path, base_dir, gems_dir| ... } click to toggle source

    # File lib/rubygems/specification_record.rb, line 204
    def map_stubs(pattern)
      @dirs.flat_map do |dir|
        base_dir = File.dirname dir
        gems_dir = File.join base_dir, "gems"
        Gem::Specification.gemspec_stubs_in(dir, pattern) {|path| yield path, base_dir, gems_dir }
      end
    end