class Bundler::Definition

Attributes

dependencies[R]
gemfiles[R]
locked_deps[R]
locked_gems[R]
lockfile[R]
platforms[R]
requires[R]
ruby_version[R]
sources[R]

Public Class Methods

build(gemfile, lockfile, unlock) click to toggle source

Given a gemfile and lockfile creates a Bundler definition

@param gemfile [Pathname] Path to Gemfile @param lockfile [Pathname,nil] Path to Gemfile.lock @param unlock [Hash, Boolean, nil] Gems that have been requested

to be updated or true if all gems should be updated

@return [Bundler::Definition]

# File bundler/definition.rb, line 27
def self.build(gemfile, lockfile, unlock)
  unlock ||= {}
  gemfile = Pathname.new(gemfile).expand_path

  raise GemfileNotFound, "#{gemfile} not found" unless gemfile.file?

  Dsl.evaluate(gemfile, lockfile, unlock)
end
new(lockfile, dependencies, sources, unlock, ruby_version = nil, optional_groups = [], gemfiles = []) click to toggle source

How does the new system work?

  • Load information from Gemfile and Lockfile

  • Invalidate stale locked specs

  • All specs from stale source are stale

  • All specs that are reachable only through a stale dependency are stale.

  • If all fresh dependencies are satisfied by the locked

specs, then we can try to resolve locally.

@param lockfile [Pathname] Path to Gemfile.lock @param dependencies [Array(Bundler::Dependency)] array of dependencies from Gemfile @param sources [Bundler::SourceList] @param unlock [Hash, Boolean, nil] Gems that have been requested

to be updated or true if all gems should be updated

@param ruby_version [Bundler::RubyVersion, nil] Requested Ruby Version @param optional_groups [Array(String)] A list of optional groups

# File bundler/definition.rb, line 54
def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, optional_groups = [], gemfiles = [])
  if [true, false].include?(unlock)
    @unlocking_bundler = false
    @unlocking = unlock
  else
    @unlocking_bundler = unlock.delete(:bundler)
    @unlocking = unlock.any? {|_k, v| !Array(v).empty? }
  end

  @dependencies    = dependencies
  @sources         = sources
  @unlock          = unlock
  @optional_groups = optional_groups
  @remote          = false
  @specs           = nil
  @ruby_version    = ruby_version
  @gemfiles        = gemfiles

  @lockfile               = lockfile
  @lockfile_contents      = String.new
  @locked_bundler_version = nil
  @locked_ruby_version    = nil
  @new_platform = nil

  if lockfile && File.exist?(lockfile)
    @lockfile_contents = Bundler.read_file(lockfile)
    @locked_gems = LockfileParser.new(@lockfile_contents)
    @locked_platforms = @locked_gems.platforms
    @platforms = @locked_platforms.dup
    @locked_bundler_version = @locked_gems.bundler_version
    @locked_ruby_version = @locked_gems.ruby_version

    if unlock != true
      @locked_deps    = @locked_gems.dependencies
      @locked_specs   = SpecSet.new(@locked_gems.specs)
      @locked_sources = @locked_gems.sources
    else
      @unlock         = {}
      @locked_deps    = {}
      @locked_specs   = SpecSet.new([])
      @locked_sources = []
    end
  else
    @unlock         = {}
    @platforms      = []
    @locked_gems    = nil
    @locked_deps    = {}
    @locked_specs   = SpecSet.new([])
    @locked_sources = []
    @locked_platforms = []
  end

  locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
  @multisource_allowed = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes? && Bundler.frozen_bundle?

  if @multisource_allowed
    unless sources.aggregate_global_source?
      msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure."

      Bundler::SharedHelpers.major_deprecation 2, msg
    end

    @sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
  end

  @unlock[:sources] ||= []
  @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
    @ruby_version.diff(locked_ruby_version_object)
  end
  @unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)

  add_current_platform unless current_ruby_platform_locked? || Bundler.frozen_bundle?

  converge_path_sources_to_gemspec_sources
  @path_changes = converge_paths
  @source_changes = converge_sources

  if @unlock[:conservative]
    @unlock[:gems] ||= @dependencies.map(&:name)
  else
    eager_unlock = expand_dependencies(@unlock[:gems] || [], true)
    @unlock[:gems] = @locked_specs.for(eager_unlock, false, false).map(&:name)
  end

  @dependency_changes = converge_dependencies
  @local_changes = converge_locals

  @locked_specs_incomplete_for_platform = !@locked_specs.for(requested_dependencies & expand_dependencies(locked_dependencies), true, true)

  @requires = compute_requires
end

Public Instance Methods

add_platform(platform) click to toggle source
# File bundler/definition.rb, line 437
def add_platform(platform)
  @new_platform ||= !@platforms.include?(platform)
  @platforms |= [platform]
end
current_dependencies() click to toggle source
# File bundler/definition.rb, line 222
def current_dependencies
  dependencies.select do |d|
    d.should_include? && !d.gem_platforms(@platforms).empty?
  end
end
dependencies_for(groups) click to toggle source
# File bundler/definition.rb, line 238
def dependencies_for(groups)
  groups.map!(&:to_sym)
  deps = current_dependencies.reject do |d|
    (d.groups & groups).empty?
  end
  expand_dependencies(deps)
end
ensure_equivalent_gemfile_and_lockfile(explicit_flag = false) click to toggle source
# File bundler/definition.rb, line 342
def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false)
  msg = String.new
  msg << "You are trying to install in deployment mode after changing\n" \
         "your Gemfile. Run `bundle install` elsewhere and add the\n" \
         "updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control."

  unless explicit_flag
    suggested_command = if Bundler.settings.locations("frozen").keys.&([:global, :local]).any?
      "bundle config unset frozen"
    elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any?
      "bundle config unset deployment"
    end
    msg << "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \
           "freeze \nby running `#{suggested_command}`."
  end

  added =   []
  deleted = []
  changed = []

  new_platforms = @platforms - @locked_platforms
  deleted_platforms = @locked_platforms - @platforms
  added.concat new_platforms.map {|p| "* platform: #{p}" }
  deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }

  new_deps = @dependencies - locked_dependencies
  deleted_deps = locked_dependencies - @dependencies

  added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
  deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?

  both_sources = Hash.new {|h, k| h[k] = [] }
  @dependencies.each {|d| both_sources[d.name][0] = d }
  locked_dependencies.each {|d| both_sources[d.name][1] = d }

  both_sources.each do |name, (dep, lock_dep)|
    next if dep.nil? || lock_dep.nil?

    gemfile_source = dep.source || sources.default_source
    lock_source = lock_dep.source || sources.default_source
    next if lock_source.include?(gemfile_source)

    gemfile_source_name = dep.source ? gemfile_source.identifier : "no specified source"
    lockfile_source_name = lock_dep.source ? lock_source.identifier : "no specified source"
    changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
  end

  reason = change_reason
  msg << "\n\n#{reason.split(", ").map(&:capitalize).join("\n")}" unless reason.strip.empty?
  msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
  msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
  msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
  msg << "\n"

  raise ProductionError, msg if added.any? || deleted.any? || changed.any? || !nothing_changed?
end
gem_version_promoter() click to toggle source
# File bundler/definition.rb, line 146
def gem_version_promoter
  @gem_version_promoter ||= begin
    locked_specs =
      if unlocking? && @locked_specs.empty? && !@lockfile_contents.empty?
        # Definition uses an empty set of locked_specs to indicate all gems
        # are unlocked, but GemVersionPromoter needs the locked_specs
        # for conservative comparison.
        Bundler::SpecSet.new(@locked_gems.specs)
      else
        @locked_specs
      end
    GemVersionPromoter.new(locked_specs, @unlock[:gems])
  end
end
groups() click to toggle source
# File bundler/definition.rb, line 273
def groups
  dependencies.map(&:groups).flatten.uniq
end
lock(file, preserve_unknown_sections = false) click to toggle source
# File bundler/definition.rb, line 277
def lock(file, preserve_unknown_sections = false)
  contents = to_lock

  # Convert to \r\n if the existing lock has them
  # i.e., Windows with `git config core.autocrlf=true`
  contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match("\r\n")

  if @locked_bundler_version
    locked_major = @locked_bundler_version.segments.first
    current_major = Gem::Version.create(Bundler::VERSION).segments.first

    if updating_major = locked_major < current_major
      Bundler.ui.warn "Warning: the lockfile is being updated to Bundler #{current_major}, " \
                      "after which you will be unable to return to Bundler #{@locked_bundler_version.segments.first}."
    end
  end

  preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))

  return if file && File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)

  if Bundler.frozen_bundle?
    Bundler.ui.error "Cannot write a changed lockfile while frozen."
    return
  end

  SharedHelpers.filesystem_access(file) do |p|
    File.open(p, "wb") {|f| f.puts(contents) }
  end
end
locked_bundler_version() click to toggle source
# File bundler/definition.rb, line 308
def locked_bundler_version
  if @locked_bundler_version && @locked_bundler_version < Gem::Version.new(Bundler::VERSION)
    new_version = Bundler::VERSION
  end

  new_version || @locked_bundler_version || Bundler::VERSION
end
locked_dependencies() click to toggle source
# File bundler/definition.rb, line 228
def locked_dependencies
  @locked_deps.values
end
locked_ruby_version() click to toggle source
# File bundler/definition.rb, line 316
def locked_ruby_version
  return unless ruby_version
  if @unlock[:ruby] || !@locked_ruby_version
    Bundler::RubyVersion.system
  else
    @locked_ruby_version
  end
end
locked_ruby_version_object() click to toggle source
# File bundler/definition.rb, line 325
def locked_ruby_version_object
  return unless @locked_ruby_version
  @locked_ruby_version_object ||= begin
    unless version = RubyVersion.from_string(@locked_ruby_version)
      raise LockfileError, "The Ruby version #{@locked_ruby_version} from " \
        "#{@lockfile} could not be parsed. " \
        "Try running bundle update --ruby to resolve this."
    end
    version
  end
end
missing_specs() click to toggle source
# File bundler/definition.rb, line 196
def missing_specs
  resolve.materialize(requested_dependencies).missing_specs
end
missing_specs?() click to toggle source
# File bundler/definition.rb, line 200
def missing_specs?
  missing = missing_specs
  return false if missing.empty?
  Bundler.ui.debug "The definition is missing #{missing.map(&:full_name)}"
  true
rescue BundlerError => e
  @resolve = nil
  @specs = nil
  @gem_version_promoter = nil

  Bundler.ui.debug "The definition is missing dependencies, failed to resolve & materialize locally (#{e})"
  true
end
most_specific_locked_platform() click to toggle source
# File bundler/definition.rb, line 447
def most_specific_locked_platform
  @platforms.min_by do |bundle_platform|
    platform_specificity_match(bundle_platform, local_platform)
  end
end
new_specs() click to toggle source
# File bundler/definition.rb, line 188
def new_specs
  specs - @locked_specs
end
nothing_changed?() click to toggle source
# File bundler/definition.rb, line 456
def nothing_changed?
  !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
end
remove_platform(platform) click to toggle source
# File bundler/definition.rb, line 442
def remove_platform(platform)
  return if @platforms.delete(Gem::Platform.new(platform))
  raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
end
removed_specs() click to toggle source
# File bundler/definition.rb, line 192
def removed_specs
  @locked_specs - specs
end
requested_dependencies() click to toggle source
# File bundler/definition.rb, line 218
def requested_dependencies
  dependencies_for(requested_groups)
end
requested_specs() click to toggle source
# File bundler/definition.rb, line 214
def requested_specs
  specs_for(requested_groups)
end
resolve() click to toggle source

Resolve all the dependencies specified in Gemfile. It ensures that dependencies that have been already resolved via locked file and are fresh are reused when resolving dependencies

@return [SpecSet] resolved dependencies

# File bundler/definition.rb, line 251
def resolve
  @resolve ||= begin
    last_resolve = converge_locked_specs
    if Bundler.frozen_bundle?
      Bundler.ui.debug "Frozen, using resolution from the lockfile"
      last_resolve
    elsif !unlocking? && nothing_changed?
      Bundler.ui.debug("Found no changes, using resolution from the lockfile")
      last_resolve
    else
      # Run a resolve against the locally available gems
      Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
      expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
      Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
    end
  end
end
resolve_only_locally!() click to toggle source
# File bundler/definition.rb, line 161
def resolve_only_locally!
  @remote = false
  sources.local_only!
  resolve
end
resolve_remotely!() click to toggle source
# File bundler/definition.rb, line 172
def resolve_remotely!
  @remote = true
  sources.remote!
  resolve
end
resolve_with_cache!() click to toggle source
# File bundler/definition.rb, line 167
def resolve_with_cache!
  sources.cached!
  resolve
end
spec_git_paths() click to toggle source
# File bundler/definition.rb, line 269
def spec_git_paths
  sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
end
specs() click to toggle source

For given dependency list returns a SpecSet with Gemspec of all the required dependencies.

1. The method first resolves the dependencies specified in Gemfile
2. After that it tries and fetches gemspec of resolved dependencies

@return [Bundler::SpecSet]

# File bundler/definition.rb, line 184
def specs
  @specs ||= materialize(requested_dependencies)
end
specs_for(groups) click to toggle source
# File bundler/definition.rb, line 232
def specs_for(groups)
  return specs if groups.empty?
  deps = dependencies_for(groups)
  materialize(deps)
end
to_lock() click to toggle source
# File bundler/definition.rb, line 337
def to_lock
  require_relative "lockfile_generator"
  LockfileGenerator.generate(self)
end
unlocking?() click to toggle source
# File bundler/definition.rb, line 460
def unlocking?
  @unlocking
end
validate_platforms!() click to toggle source
# File bundler/definition.rb, line 429
def validate_platforms!
  return if current_platform_locked?

  raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
    "but your local platform is #{Bundler.local_platform}. " \
    "Add the current platform to the lockfile with `bundle lock --add-platform #{Bundler.local_platform}` and try again."
end
validate_ruby!() click to toggle source
# File bundler/definition.rb, line 404
def validate_ruby!
  return unless ruby_version

  if diff = ruby_version.diff(Bundler::RubyVersion.system)
    problem, expected, actual = diff

    msg = case problem
          when :engine
            "Your Ruby engine is #{actual}, but your Gemfile specified #{expected}"
          when :version
            "Your Ruby version is #{actual}, but your Gemfile specified #{expected}"
          when :engine_version
            "Your #{Bundler::RubyVersion.system.engine} version is #{actual}, but your Gemfile specified #{ruby_version.engine} #{expected}"
          when :patchlevel
            if !expected.is_a?(String)
              "The Ruby patchlevel in your Gemfile must be a string"
            else
              "Your Ruby patchlevel is #{actual}, but your Gemfile specified #{expected}"
            end
    end

    raise RubyVersionMismatch, msg
  end
end
validate_runtime!() click to toggle source
# File bundler/definition.rb, line 399
def validate_runtime!
  validate_ruby!
  validate_platforms!
end

Private Instance Methods

add_current_platform() click to toggle source
# File bundler/definition.rb, line 507
def add_current_platform
  add_platform(local_platform)
end
additional_base_requirements_for_resolve() click to toggle source
# File bundler/definition.rb, line 819
def additional_base_requirements_for_resolve
  return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
  converge_specs(@locked_gems.specs).map do |locked_spec|
    name = locked_spec.name
    dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
    DepProxy.get_proxy(dep, locked_spec.platform)
  end
end
change_reason() click to toggle source
# File bundler/definition.rb, line 511
def change_reason
  if unlocking?
    unlock_reason = @unlock.reject {|_k, v| Array(v).empty? }.map do |k, v|
      if v == true
        k.to_s
      else
        v = Array(v)
        "#{k}: (#{v.join(", ")})"
      end
    end.join(", ")
    return "bundler is unlocking #{unlock_reason}"
  end
  [
    [@source_changes, "the list of sources changed"],
    [@dependency_changes, "the dependencies in your gemfile changed"],
    [@new_platform, "you added a new platform to your gemfile"],
    [@path_changes, "the gemspecs for path gems changed"],
    [@local_changes, "the gemspecs for git local gems changed"],
    [@locked_specs_incomplete_for_platform, "the lockfile does not have all gems needed for the current platform"],
  ].select(&:first).map(&:last).join(", ")
end
compute_requires() click to toggle source
# File bundler/definition.rb, line 808
def compute_requires
  dependencies.reduce({}) do |requires, dep|
    next requires unless dep.should_include?
    requires[dep.name] = Array(dep.autorequire || dep.name).map do |file|
      # Allow `require: true` as an alias for `require: <name>`
      file == true ? dep.name : file
    end
    requires
  end
end
converge_dependencies() click to toggle source
# File bundler/definition.rb, line 629
def converge_dependencies
  changes = false

  @dependencies.each do |dep|
    if dep.source
      dep.source = sources.get(dep.source)
    end

    unless locked_dep = @locked_deps[dep.name]
      changes = true
      next
    end

    # Gem::Dependency#== matches Gem::Dependency#type. As the lockfile
    # doesn't carry a notion of the dependency type, if you use
    # add_development_dependency in a gemspec that's loaded with the gemspec
    # directive, the lockfile dependencies and resolved dependencies end up
    # with a mismatch on #type. Work around that by setting the type on the
    # dep from the lockfile.
    locked_dep.instance_variable_set(:@type, dep.type)

    # We already know the name matches from the hash lookup
    # so we only need to check the requirement now
    changes ||= dep.requirement != locked_dep.requirement
  end

  changes
end
converge_locals() click to toggle source

Get all locals and override their matching sources. Return true if any of the locals changed (for example, they point to a new revision) or depend on new specs.

# File bundler/definition.rb, line 566
def converge_locals
  locals = []

  Bundler.settings.local_overrides.map do |k, v|
    spec   = @dependencies.find {|s| s.name == k }
    source = spec && spec.source
    if source && source.respond_to?(:local_override!)
      source.unlock! if @unlock[:gems].include?(spec.name)
      locals << [source, source.local_override!(v)]
    end
  end

  sources_with_changes = locals.select do |source, changed|
    changed || specs_changed?(source)
  end.map(&:first)
  !sources_with_changes.each {|source| @unlock[:sources] << source.name }.empty?
end
converge_locked_specs() click to toggle source

Remove elements from the locked specs that are expired. This will most commonly happen if the Gemfile has changed since the lockfile was last generated

# File bundler/definition.rb, line 661
def converge_locked_specs
  resolve = converge_specs(@locked_specs)

  diff = nil

  # Now, we unlock any sources that do not have anymore gems pinned to it
  sources.all_sources.each do |source|
    next unless source.respond_to?(:unlock!)

    unless resolve.any? {|s| s.source == source }
      diff ||= @locked_specs.to_a - resolve.to_a
      source.unlock! if diff.any? {|s| s.source == source }
    end
  end

  resolve
end
converge_path_source_to_gemspec_source(source) click to toggle source
# File bundler/definition.rb, line 590
def converge_path_source_to_gemspec_source(source)
  return source unless source.instance_of?(Source::Path)
  gemspec_source = sources.path_sources.find {|s| s.is_a?(Source::Gemspec) && s.as_path_source == source }
  gemspec_source || source
end
converge_path_sources_to_gemspec_sources() click to toggle source
# File bundler/definition.rb, line 596
def converge_path_sources_to_gemspec_sources
  @locked_sources.map! do |source|
    converge_path_source_to_gemspec_source(source)
  end
  @locked_specs.each do |spec|
    spec.source &&= converge_path_source_to_gemspec_source(spec.source)
  end
  @locked_deps.each do |_, dep|
    dep.source &&= converge_path_source_to_gemspec_source(dep.source)
  end
end
converge_paths() click to toggle source
# File bundler/definition.rb, line 584
def converge_paths
  sources.path_sources.any? do |source|
    specs_changed?(source)
  end
end
converge_sources() click to toggle source
# File bundler/definition.rb, line 608
def converge_sources
  # Replace the sources from the Gemfile with the sources from the Gemfile.lock,
  # if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent
  # source in the Gemfile.lock, use the one from the Gemfile.
  changes = sources.replace_sources!(@locked_sources)

  sources.all_sources.each do |source|
    # If the source is unlockable and the current command allows an unlock of
    # the source (for example, you are doing a `bundle update <foo>` of a git-pinned
    # gem), unlock it. For git sources, this means to unlock the revision, which
    # will cause the `ref` used to be the most recent for the branch (or master) if
    # an explicit `ref` is not used.
    if source.respond_to?(:unlock!) && @unlock[:sources].include?(source.name)
      source.unlock!
      changes = true
    end
  end

  changes
end
converge_specs(specs) click to toggle source
# File bundler/definition.rb, line 679
def converge_specs(specs)
  deps = []
  converged = []
  specs.each do |s|
    # Replace the locked dependency's source with the equivalent source from the Gemfile
    dep = @dependencies.find {|d| s.satisfies?(d) }

    if dep && (!dep.source || s.source.include?(dep.source))
      deps << dep
    end

    s.source = (dep && dep.source) || sources.get(s.source) || sources.default_source unless Bundler.frozen_bundle?

    next if @unlock[:sources].include?(s.source.name)

    # If the spec is from a path source and it doesn't exist anymore
    # then we unlock it.

    # Path sources have special logic
    if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
      new_specs = begin
        s.source.specs
      rescue PathError, GitError
        # if we won't need the source (according to the lockfile),
        # don't error if the path/git source isn't available
        next if specs.
                for(requested_dependencies, false, true).
                none? {|locked_spec| locked_spec.source == s.source }

        raise
      end

      new_spec = new_specs[s].first

      # If the spec is no longer in the path source, unlock it. This
      # commonly happens if the version changed in the gemspec
      next unless new_spec

      s.dependencies.replace(new_spec.dependencies)
    end

    if dep.nil? && requested_dependencies.find {|d| s.name == d.name }
      @unlock[:gems] << s.name
    else
      converged << s
    end
  end

  resolve = SpecSet.new(converged)
  SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) })
end
current_platform_locked?() click to toggle source
# File bundler/definition.rb, line 501
def current_platform_locked?
  @platforms.any? do |bundle_platform|
    MatchPlatform.platforms_match?(bundle_platform, Bundler.local_platform)
  end
end
current_ruby_platform_locked?() click to toggle source
# File bundler/definition.rb, line 495
def current_ruby_platform_locked?
  return false unless generic_local_platform == Gem::Platform::RUBY

  current_platform_locked?
end
dependencies_for_source_changed?(source, locked_source = source) click to toggle source
# File bundler/definition.rb, line 545
def dependencies_for_source_changed?(source, locked_source = source)
  deps_for_source = @dependencies.select {|s| s.source == source }
  locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }

  deps_for_source.uniq.sort != locked_deps_for_source.sort
end
expand_dependencies(dependencies, remote = false) click to toggle source
# File bundler/definition.rb, line 757
def expand_dependencies(dependencies, remote = false)
  deps = []
  dependencies.each do |dep|
    dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name)
    next unless remote || dep.current_platform?
    target_platforms = dep.gem_platforms(remote ? @platforms : [generic_local_platform])
    deps += expand_dependency_with_platforms(dep, target_platforms)
  end
  deps
end
expand_dependency_with_platforms(dep, platforms) click to toggle source
# File bundler/definition.rb, line 768
def expand_dependency_with_platforms(dep, platforms)
  platforms.map do |p|
    DepProxy.get_proxy(dep, p)
  end
end
lockfiles_equal?(current, proposed, preserve_unknown_sections) click to toggle source
# File bundler/definition.rb, line 795
def lockfiles_equal?(current, proposed, preserve_unknown_sections)
  if preserve_unknown_sections
    sections_to_ignore = LockfileParser.sections_to_ignore(@locked_bundler_version)
    sections_to_ignore += LockfileParser.unknown_sections_in_lockfile(current)
    sections_to_ignore += LockfileParser::ENVIRONMENT_VERSION_SECTIONS
    pattern = /#{Regexp.union(sections_to_ignore)}\n(\s{2,}.*\n)+/
    whitespace_cleanup = /\n{2,}/
    current = current.gsub(pattern, "\n").gsub(whitespace_cleanup, "\n\n").strip
    proposed = proposed.gsub(pattern, "\n").gsub(whitespace_cleanup, "\n\n").strip
  end
  current == proposed
end
materialize(dependencies) click to toggle source
# File bundler/definition.rb, line 466
def materialize(dependencies)
  specs = resolve.materialize(dependencies)
  missing_specs = specs.missing_specs

  if missing_specs.any?
    missing_specs.each do |s|
      locked_gem = @locked_specs[s.name].last
      next if locked_gem.nil? || locked_gem.version != s.version || !@remote
      raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
                         "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
                         "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
                         "removed in order to install."
    end

    raise GemNotFound, "Could not find #{missing_specs.map(&:full_name).join(", ")} in any of the sources"
  end

  unless specs["bundler"].any?
    bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
    specs["bundler"] = bundler
  end

  specs
end
metadata_dependencies() click to toggle source
# File bundler/definition.rb, line 731
def metadata_dependencies
  @metadata_dependencies ||= begin
    ruby_versions = ruby_version_requirements(@ruby_version)
    [
      Dependency.new("Ruby\0", ruby_versions),
      Dependency.new("RubyGems\0", Gem::VERSION),
    ]
  end
end
precompute_source_requirements_for_indirect_dependencies?() click to toggle source
# File bundler/definition.rb, line 491
def precompute_source_requirements_for_indirect_dependencies?
  @remote && sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
end
pretty_dep(dep, source = false) click to toggle source
# File bundler/definition.rb, line 533
def pretty_dep(dep, source = false)
  SharedHelpers.pretty_dependency(dep, source)
end
requested_groups() click to toggle source
# File bundler/definition.rb, line 791
def requested_groups
  groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
end
ruby_version_requirements(ruby_version) click to toggle source
# File bundler/definition.rb, line 741
def ruby_version_requirements(ruby_version)
  return [] unless ruby_version
  if ruby_version.patchlevel
    [ruby_version.to_gem_version_with_patchlevel]
  else
    ruby_version.versions.map do |version|
      requirement = Gem::Requirement.new(version)
      if requirement.exact?
        "~> #{version}.0"
      else
        requirement
      end
    end
  end
end
source_map() click to toggle source
# File bundler/definition.rb, line 828
def source_map
  @source_map ||= SourceMap.new(sources, dependencies)
end
source_requirements() click to toggle source
# File bundler/definition.rb, line 774
def source_requirements
  # Record the specs available in each gem's source, so that those
  # specs will be available later when the resolver knows where to
  # look for that gemspec (or its dependencies)
  source_requirements = if precompute_source_requirements_for_indirect_dependencies?
    { :default => sources.default_source }.merge(source_map.all_requirements)
  else
    { :default => Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
  end
  metadata_dependencies.each do |dep|
    source_requirements[dep.name] = sources.metadata_source
  end
  source_requirements[:default_bundler] = source_requirements["bundler"] || sources.default_source
  source_requirements["bundler"] = sources.metadata_source # needs to come last to override
  source_requirements
end
specs_changed?(source) click to toggle source

Check if the specs of the given source changed according to the locked source.

# File bundler/definition.rb, line 539
def specs_changed?(source)
  locked = @locked_sources.find {|s| s == source }

  !locked || dependencies_for_source_changed?(source, locked) || specs_for_source_changed?(source)
end
specs_for_source_changed?(source) click to toggle source
# File bundler/definition.rb, line 552
def specs_for_source_changed?(source)
  locked_index = Index.new
  locked_index.use(@locked_specs.select {|s| source.can_lock?(s) })

  # order here matters, since Index#== is checking source.specs.include?(locked_index)
  locked_index != source.specs
rescue PathError, GitError => e
  Bundler.ui.debug "Assuming that #{source} has not changed since fetching its specs errored (#{e})"
  false
end