Class: Bundler::LockfileParser

Inherits:
Object
  • Object
show all
Includes:
GemHelpers
Defined in:
lib/bundler/lockfile_parser.rb

Defined Under Namespace

Classes: Position

Constant Summary collapse

BUNDLED =
"BUNDLED WITH"
DEPENDENCIES =
"DEPENDENCIES"
CHECKSUMS =
"CHECKSUMS"
PLATFORMS =
"PLATFORMS"
RUBY =
"RUBY VERSION"
GIT =
"GIT"
GEM =
"GEM"
PATH =
"PATH"
PLUGIN =
"PLUGIN SOURCE"
SPECS =
"  specs:"
OPTIONS =
/^  ([a-z]+): (.*)$/i
SOURCE =
[GIT, GEM, PATH, PLUGIN].freeze
SECTIONS_BY_VERSION_INTRODUCED =
{
  Gem::Version.create("1.0") => [DEPENDENCIES, PLATFORMS, GIT, GEM, PATH].freeze,
  Gem::Version.create("1.10") => [BUNDLED].freeze,
  Gem::Version.create("1.12") => [RUBY].freeze,
  Gem::Version.create("1.13") => [PLUGIN].freeze,
  Gem::Version.create("2.5.0") => [CHECKSUMS].freeze,
}.freeze
KNOWN_SECTIONS =
SECTIONS_BY_VERSION_INTRODUCED.values.flatten!.freeze
ENVIRONMENT_VERSION_SECTIONS =
[BUNDLED, RUBY].freeze

Constants included from GemHelpers

GemHelpers::GENERICS, GemHelpers::GENERIC_CACHE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from GemHelpers

generic, generic_local_platform, generic_local_platform_is_ruby?, local_platform, platform_specificity_match, same_deps, same_specificity, select_all_platform_match, select_best_local_platform_match, select_best_platform_match, sort_and_filter_best_platform_match, sort_best_platform_match

Constructor Details

#initialize(lockfile) ⇒ LockfileParser

Returns a new instance of LockfileParser.



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/bundler/lockfile_parser.rb', line 97

def initialize(lockfile)
  @platforms    = []
  @sources      = []
  @dependencies = {}
  @parse_method = nil
  @specs        = {}
  @lockfile_path = begin
    SharedHelpers.relative_lockfile_path
  rescue GemfileNotFound
    "Gemfile.lock"
  end
  @pos = Position.new(1, 1)

  if lockfile.match?(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
    raise LockfileError, "Your #{@lockfile_path} contains merge conflicts.\n" \
      "Run `git checkout HEAD -- #{@lockfile_path}` first to get a clean lock."
  end

  lockfile.split(/((?:\r?\n)+)/) do |line|
    # split alternates between the line and the following whitespace
    next @pos.advance!(line) if line.match?(/^\s*$/)

    if SOURCE.include?(line)
      @parse_method = :parse_source
      parse_source(line)
    elsif line == DEPENDENCIES
      @parse_method = :parse_dependency
    elsif line == CHECKSUMS
      # This is a temporary solution to make this feature disabled by default
      # for all gemfiles that don't already explicitly include the feature.
      @checksums = true
      @parse_method = :parse_checksum
    elsif line == PLATFORMS
      @parse_method = :parse_platform
    elsif line == RUBY
      @parse_method = :parse_ruby
    elsif line == BUNDLED
      @parse_method = :parse_bundled_with
    elsif /^[^\s]/.match?(line)
      @parse_method = nil
    elsif @parse_method
      send(@parse_method, line)
    end
    @pos.advance!(line)
  end
  @most_specific_locked_platform = @platforms.min_by do |bundle_platform|
    platform_specificity_match(bundle_platform, local_platform)
  end
  @specs = @specs.values.sort_by!(&:full_name).each do |spec|
    spec.most_specific_locked_platform = @most_specific_locked_platform
  end
rescue ArgumentError => e
  Bundler.ui.debug(e)
  raise LockfileError, "Your lockfile is unreadable. Run `rm #{@lockfile_path}` " \
    "and then `bundle install` to generate a new lockfile. The error occurred while " \
    "evaluating #{@lockfile_path}:#{@pos}"
end

Instance Attribute Details

#bundler_versionObject (readonly)

Returns the value of attribute bundler_version.



29
30
31
# File 'lib/bundler/lockfile_parser.rb', line 29

def bundler_version
  @bundler_version
end

#dependenciesObject (readonly)

Returns the value of attribute dependencies.



29
30
31
# File 'lib/bundler/lockfile_parser.rb', line 29

def dependencies
  @dependencies
end

#most_specific_locked_platformObject (readonly)

Returns the value of attribute most_specific_locked_platform.



29
30
31
# File 'lib/bundler/lockfile_parser.rb', line 29

def most_specific_locked_platform
  @most_specific_locked_platform
end

#platformsObject (readonly)

Returns the value of attribute platforms.



29
30
31
# File 'lib/bundler/lockfile_parser.rb', line 29

def platforms
  @platforms
end

#ruby_versionObject (readonly)

Returns the value of attribute ruby_version.



29
30
31
# File 'lib/bundler/lockfile_parser.rb', line 29

def ruby_version
  @ruby_version
end

#sourcesObject (readonly)

Returns the value of attribute sources.



29
30
31
# File 'lib/bundler/lockfile_parser.rb', line 29

def sources
  @sources
end

#specsObject (readonly)

Returns the value of attribute specs.



29
30
31
# File 'lib/bundler/lockfile_parser.rb', line 29

def specs
  @specs
end

Class Method Details

.bundled_withObject



87
88
89
90
91
92
93
94
95
# File 'lib/bundler/lockfile_parser.rb', line 87

def self.bundled_with
  lockfile = Bundler.default_lockfile
  return unless lockfile.file?

  lockfile_contents = Bundler.read_file(lockfile)
  return unless lockfile_contents.include?(BUNDLED)

  lockfile_contents.split(BUNDLED).last.strip
end

.sections_in_lockfile(lockfile_contents) ⇒ Object



66
67
68
69
70
# File 'lib/bundler/lockfile_parser.rb', line 66

def self.sections_in_lockfile(lockfile_contents)
  sections = lockfile_contents.scan(/^\w[\w ]*$/)
  sections.uniq!
  sections
end

.sections_to_ignore(base_version = nil) ⇒ Object



76
77
78
79
80
81
82
83
84
85
# File 'lib/bundler/lockfile_parser.rb', line 76

def self.sections_to_ignore(base_version = nil)
  base_version &&= base_version.release
  base_version ||= Gem::Version.create("1.0")
  attributes = []
  SECTIONS_BY_VERSION_INTRODUCED.each do |version, introduced|
    next if version <= base_version
    attributes += introduced
  end
  attributes
end

.unknown_sections_in_lockfile(lockfile_contents) ⇒ Object



72
73
74
# File 'lib/bundler/lockfile_parser.rb', line 72

def self.unknown_sections_in_lockfile(lockfile_contents)
  sections_in_lockfile(lockfile_contents) - KNOWN_SECTIONS
end

Instance Method Details

#may_include_redundant_platform_specific_gems?Boolean

Returns:

  • (Boolean)


155
156
157
# File 'lib/bundler/lockfile_parser.rb', line 155

def may_include_redundant_platform_specific_gems?
  bundler_version.nil? || bundler_version < Gem::Version.new("1.16.2")
end