Class: Bundler::Definition

### Home Classes Methods

### In Files

- lib/bundler/definition.rb

### Parent

Object

### Methods

- ::build
- ::new
- #current_dependencies
- #ensure_equivalent_gemfile_and_lockfile
- #fixup_dependency_types!
- #groups
- #index
- #lock
- #missing_specs
- #new_platform?
- #new_specs
- #removed_specs
- #requested_specs
- #resolve
- #resolve_remotely!
- #resolve_with_cache!
- #rubygems_index
- #rubygems_remotes
- #specs
- #specs_for
- #to_lock
- #validate_ruby!

### Included Modules

- Bundler::GemHelpers

### Files

- bundle
- bundle-config
- bundle-config.txt
- bundle-exec
- bundle-exec.txt
- bundle-install
- bundle-install.txt
- bundle-package
- bundle-package.txt
- bundle-platform
- bundle-platform.txt
- bundle-update
- bundle-update.txt
- bundle.txt
- gemfile.5.txt
- Executable
- Gemfile

### Class/Module Index

Quicksearch

- Bundler
- Bundler::BundlerError
- Bundler::CLI
- Bundler::Definition
- Bundler::DepProxy
- Bundler::Dependency
- Bundler::Deployment
- Bundler::Deprecate
- Bundler::DeprecatedError
- Bundler::Dsl
- Bundler::EndpointSpecification
- Bundler::Env
- Bundler::Environment
- Bundler::Fetcher
- Bundler::Fetcher::CertificateFailureError
- Bundler::Fetcher::FallbackError
- Bundler::Fetcher::SSLError
- Bundler::GemHelper
- Bundler::GemHelpers
- Bundler::GemInstaller
- Bundler::GemNotFound
- Bundler::GemfileError
- Bundler::GemfileNotFound
- Bundler::GemspecError
- Bundler::GitError
- Bundler::Graph
- Bundler::Graph::GraphVizClient
- Bundler::HTTPError
- Bundler::Index
- Bundler::Injector
- Bundler::InstallError
- Bundler::InstallHookError
- Bundler::Installer
- Bundler::InvalidOption
- Bundler::InvalidSpecSet
- Bundler::LazySpecification
- Bundler::LockfileError
- Bundler::LockfileParser
- Bundler::MarshalError
- Bundler::MatchPlatform
- Bundler::PathError
- Bundler::ProductionError
- Bundler::RemoteSpecification
- Bundler::Resolver
- Bundler::Resolver::SpecGroup
- Bundler::RubyDsl
- Bundler::RubyVersion
- Bundler::RubyVersionMismatch
- Bundler::RubygemsIntegration
- Bundler::RubygemsIntegration::AlmostModern
- Bundler::RubygemsIntegration::Ancient
- Bundler::RubygemsIntegration::Future
- Bundler::RubygemsIntegration::Gem
- Bundler::RubygemsIntegration::Gem::SourceIndex
- Bundler::RubygemsIntegration::Legacy
- Bundler::RubygemsIntegration::Modern
- Bundler::RubygemsIntegration::Transitional
- Bundler::Runtime
- Bundler::SecurityError
- Bundler::Settings
- Bundler::SharedHelpers
- Bundler::SimilarityDetector
- Bundler::Source
- Bundler::Source::Git
- Bundler::Source::Git::GitProxy
- Bundler::Source::Path
- Bundler::Source::Path::Installer
- Bundler::Source::Rubygems
- Bundler::SpecSet
- Bundler::SystemRubyVersion
- Bundler::UI
- Bundler::UI::RGProxy
- Bundler::UI::Shell
- Bundler::VersionConflict
- Gem
- Gem::Dependency
- Gem::Platform
- Gem::Requirement
- Gem::Specification
- Object

No matching classes.

# Bundler::Definition

### Attributes

dependencies[R]
locked_deps[R]
platforms[R]
ruby_version[R]
sources[R]

### Public Class Methods

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

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

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

      Dsl.evaluate(gemfile, lockfile, unlock)
    end

new(lockfile, dependencies, sources, unlock, ruby_version = nil) 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.

    # File lib/bundler/definition.rb, line 34
    def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil)
      @unlocking = unlock == true || !unlock.empty?

      @dependencies, @sources, @unlock = dependencies, sources, unlock
      @remote            = false
      @specs             = nil
      @lockfile_contents = ""
      @ruby_version      = ruby_version

      if lockfile && File.exists?(lockfile)
        @lockfile_contents = Bundler.read_file(lockfile)
        locked = LockfileParser.new(@lockfile_contents)
        @platforms      = locked.platforms

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

      @unlock[:gems] ||= []
      @unlock[:sources] ||= []

      current_platform = Bundler.rubygems.platforms.map { |p| generic(p) }.compact.last
      @new_platform = !@platforms.include?(current_platform)
      @platforms |= [current_platform]

      @path_changes = converge_paths
      eager_unlock = expand_dependencies(@unlock[:gems])
      @unlock[:gems] = @locked_specs.for(eager_unlock).map { |s| s.name }

      @source_changes = converge_sources
      @dependency_changes = converge_dependencies
      @local_changes = converge_locals

      fixup_dependency_types!
    end

### Public Instance Methods

current_dependencies() click to toggle source

    # File lib/bundler/definition.rb, line 152
    def current_dependencies
      dependencies.reject { |d| !d.should_include? }
    end

ensure_equivalent_gemfile_and_lockfile(explicit_flag = false) click to toggle source

    # File lib/bundler/definition.rb, line 282
    def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false)
      changes = false

      msg = "You are trying to install in deployment mode after changing\n"              "your Gemfile. Run `bundle install` elsewhere and add the\n"              "updated Gemfile.lock to version control."

      unless explicit_flag
        msg += "\n\nIf this is a development machine, remove the Gemfile "                 "freeze \nby running `bundle install --no-deployment`."
      end

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

      if @locked_sources != @sources
        new_sources = @sources - @locked_sources
        deleted_sources = @locked_sources - @sources

        if new_sources.any?
          added.concat new_sources.map { |source| "* source: #{source}" }
        end

        if deleted_sources.any?
          deleted.concat deleted_sources.map { |source| "* source: #{source}" }
        end

        changes = true
      end

      both_sources = Hash.new { |h,k| h[k] = ["no specified source", "no specified source"] }
      @dependencies.each { |d| both_sources[d.name][0] = d.source if d.source }
      @locked_deps.each  { |d| both_sources[d.name][1] = d.source if d.source }
      both_sources.delete_if { |k,v| v[0] == v[1] }

      if @dependencies != @locked_deps
        new_deps = @dependencies - @locked_deps
        deleted_deps = @locked_deps - @dependencies

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

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

        both_sources.each do |name, sources|
          changed << "* #{name} from `#{sources[0]}` to `#{sources[1]}`"
        end

        changes = true
      end

      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?
    end

fixup_dependency_types!() click to toggle source

    # File lib/bundler/definition.rb, line 84
    def fixup_dependency_types!
      # XXX This is a temporary workaround for a bug when using rubygems 1.8.15
      # where 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.
      # Test coverage to catch a regression on this is in gemspec_spec.rb
      @dependencies.each do |d|
        if ld = @locked_deps.find { |l| l.name == d.name }
          ld.instance_variable_set(:@type, d.type)
        end
      end
    end

groups() click to toggle source

    # File lib/bundler/definition.rb, line 215
    def groups
      dependencies.map { |d| d.groups }.flatten.uniq
    end

index() click to toggle source

    # File lib/bundler/definition.rb, line 184
    def index
      @index ||= Index.build do |idx|
        dependency_names = @dependencies.dup || []
        dependency_names.map! {|d| d.name }

        @sources.each do |s|
          if s.is_a?(Bundler::Source::Rubygems)
            s.dependency_names = dependency_names.uniq
            idx.add_source s.specs
          else
            source_index = s.specs
            dependency_names += source_index.unmet_dependency_names
            idx.add_source source_index
          end
        end
      end
    end

lock(file) click to toggle source

    # File lib/bundler/definition.rb, line 219
    def lock(file)
      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")

      return if @lockfile_contents == contents

      if Bundler.settings[:frozen]
        Bundler.ui.error "Cannot write a changed lockfile while frozen."
        return
      end

      File.open(file, 'wb'){|f| f.puts(contents) }
    rescue Errno::EACCES
      raise Bundler::InstallError,
        "There was an error while trying to write to Gemfile.lock. It is likely that \n"          "you need to allow write permissions for the file at path: \n"          "#{File.expand_path(file)}"
    end

missing_specs() click to toggle source

    # File lib/bundler/definition.rb, line 138
    def missing_specs
      missing = []
      resolve.materialize(requested_dependencies, missing)
      missing
    end

new_platform?() click to toggle source

    # File lib/bundler/definition.rb, line 134
    def new_platform?
      @new_platform
    end

new_specs() click to toggle source

    # File lib/bundler/definition.rb, line 126
    def new_specs
      specs - @locked_specs
    end

removed_specs() click to toggle source

    # File lib/bundler/definition.rb, line 130
    def removed_specs
      @locked_specs - specs
    end

requested_specs() click to toggle source

    # File lib/bundler/definition.rb, line 144
    def requested_specs
      @requested_specs ||= begin
        groups = self.groups - Bundler.settings.without
        groups.map! { |g| g.to_sym }
        specs_for(groups)
      end
    end

resolve() click to toggle source

    # File lib/bundler/definition.rb, line 162
    def resolve
      @resolve ||= begin
        if Bundler.settings[:frozen] || (!@unlocking && nothing_changed?)
          @locked_specs
        else
          last_resolve = converge_locked_specs

          # 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 = {}
          dependencies.each do |dep|
            next unless dep.source
            source_requirements[dep.name] = dep.source.specs
          end

          # Run a resolve against the locally available gems
          last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve)
        end
      end
    end

resolve_remotely!() click to toggle source

    # File lib/bundler/definition.rb, line 105
    def resolve_remotely!
      raise "Specs already loaded" if @specs
      @remote = true
      @sources.each { |s| s.remote! }
      specs
    end

resolve_with_cache!() click to toggle source

    # File lib/bundler/definition.rb, line 99
    def resolve_with_cache!
      raise "Specs already loaded" if @specs
      @sources.each { |s| s.cached! }
      specs
    end

rubygems_index() click to toggle source

used when frozen is enabled so we can find the bundler spec, even if (say) a git gem is not checked out.

    # File lib/bundler/definition.rb, line 204
    def rubygems_index
      @rubygems_index ||= Index.build do |idx|
        rubygems = @sources.find{|s| s.is_a?(Source::Rubygems) }
        idx.add_source rubygems.specs
      end
    end

rubygems_remotes() click to toggle source

    # File lib/bundler/definition.rb, line 211
    def rubygems_remotes
      @sources.select{|s| s.is_a?(Source::Rubygems) }.map{|s| s.remotes }.flatten
    end

specs() click to toggle source

    # File lib/bundler/definition.rb, line 112
    def specs
      @specs ||= begin
        specs = resolve.materialize(requested_dependencies)

        unless specs["bundler"].any?
          local = Bundler.settings[:frozen] ? rubygems_index : index
          bundler = local.search(Gem::Dependency.new('bundler', VERSION)).last
          specs["bundler"] = bundler if bundler
        end

        specs
      end
    end

specs_for(groups) click to toggle source

    # File lib/bundler/definition.rb, line 156
    def specs_for(groups)
      deps = dependencies.select { |d| (d.groups & groups).any? }
      deps.delete_if { |d| !d.should_include? }
      specs.for(expand_dependencies(deps))
    end

to_lock() click to toggle source

    # File lib/bundler/definition.rb, line 241
    def to_lock
      out = ""

      sorted_sources.each do |source|
        # Add the source header
        out << source.to_lock
        # Find all specs for this source
        resolve.
          select  { |s| s.source == source }.
          # This needs to be sorted by full name so that
          # gems with the same name, but different platform
          # are ordered consistantly
          sort_by { |s| s.full_name }.
          each do |spec|
            next if spec.name == 'bundler'
            out << spec.to_lock
        end
        out << "\n"
      end

      out << "PLATFORMS\n"

      platforms.map { |p| p.to_s }.sort.each do |p|
        out << "  #{p}\n"
      end

      out << "\n"
      out << "DEPENDENCIES\n"

      handled = []
      dependencies.
        sort_by { |d| d.to_s }.
        each do |dep|
          next if handled.include?(dep.name)
          out << dep.to_lock
          handled << dep.name
      end

      out
    end

validate_ruby!() click to toggle source

    # File lib/bundler/definition.rb, line 345
    def validate_ruby!
      return unless ruby_version

      system_ruby_version = Bundler::SystemRubyVersion.new
      if diff = ruby_version.diff(system_ruby_version)
        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 #{system_ruby_version.engine} version is #{actual}, but your Gemfile specified #{ruby_version.engine} #{expected}"
        end

        raise RubyVersionMismatch, msg
      end
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.