class Berkshelf::Lockfile::LockfileParser

The class responsible for parsing the lockfile and turning it into a useful data structure.

Constants

DEPENDENCIES_PATTERN
DEPENDENCY_PATTERN
NAME_VERSION
OPTION_PATTERN

Public Class Methods

new(lockfile) click to toggle source

Create a new lockfile parser.

@param [Lockfile]

# File lib/berkshelf/lockfile.rb, line 525
def initialize(lockfile)
  @lockfile  = lockfile
  @berksfile = lockfile.berksfile
end

Public Instance Methods

run() click to toggle source

Parse the lockfile contents, adding the correct things to the lockfile.

@return [true]

# File lib/berkshelf/lockfile.rb, line 533
def run
  @parsed_dependencies = {}

  contents = File.read(@lockfile.filepath)

  if contents.strip.empty?
    Berkshelf.formatter.warn "Your lockfile at '#{@lockfile.filepath}' " \
      "is empty. I am going to parse it anyway, but there is a chance " \
      "that a larger problem is at play. If you manually edited your " \
      "lockfile, you may have corrupted it."
  end

  if contents.strip[0] == "{"
    Berkshelf.formatter.warn "It looks like you are using an older " \
      "version of the lockfile. Attempting to convert..."

    dependencies = "#{Lockfile::DEPENDENCIES}\n"
    graph        = "#{Lockfile::GRAPH}\n"

    begin
      hash = JSON.parse(contents)
    rescue JSON::ParserError
      Berkshelf.formatter.warn "Could not convert lockfile! This is a " \
      "problem. You see, previous versions of the lockfile were " \
      "actually a lie. It lied to you about your version locks, and we " \
      "are really sorry about that.\n\n" \
      "Here's the good news - we fixed it!\n\n" \
      "Here's the bad news - you probably should not trust your old " \
      "lockfile. You should manually delete your old lockfile and " \
      "re-run the installer."
    end

    hash["dependencies"] && hash["dependencies"].sort .each do |name, info|
      dependencies << "  #{name} (>= 0.0.0)\n"
      info.each do |key, value|
        unless key == "locked_version"
          dependencies << "    #{key}: #{value}\n"
        end
      end

      graph << "  #{name} (#{info["locked_version"]})\n"
    end

    contents = "#{dependencies}\n#{graph}"
  end

  contents.split(/(?:\r?\n)+/).each do |line|
    if line == Lockfile::DEPENDENCIES
      @state = :dependency
    elsif line == Lockfile::GRAPH
      @state = :graph
    else
      send("parse_#{@state}", line)
    end
  end

  @parsed_dependencies.each do |name, options|
    graph_item = @lockfile.graph.find(name)
    options[:locked_version] = graph_item.version if graph_item

    dependency = Dependency.new(@berksfile, name, options)
    @lockfile.add(dependency)
  end

  true
end

Private Instance Methods

parse_dependency(line) click to toggle source

Parse a dependency line.

@param [String] line

# File lib/berkshelf/lockfile.rb, line 605
def parse_dependency(line)
  if line =~ DEPENDENCY_PATTERN
    name, version = $1, $2

    @parsed_dependencies[name] ||= {}
    @parsed_dependencies[name][:constraint] = version if version
    @current_dependency = @parsed_dependencies[name]
  elsif line =~ OPTION_PATTERN
    key, value = $1, $2
    @current_dependency[key.to_sym] = value
  end
end
parse_graph(line) click to toggle source

Parse a graph line.

@param [String] line

# File lib/berkshelf/lockfile.rb, line 621
def parse_graph(line)
  if line =~ DEPENDENCY_PATTERN
    name, version = $1, $2

    @lockfile.graph.find(name) || @lockfile.graph.add(name, version)
    @current_lock = name
  elsif line =~ DEPENDENCIES_PATTERN
    name, constraint = $1, $2
    @lockfile.graph.find(@current_lock).add_dependency(name, constraint)
  end
end