class Gem::Comparator::GemfileComparator

Gem::Comparator::GemfileComparator can compare dependencies between gem's Gemfiles based on the given Gem::Package objects

To compare Gemfiles it needs to extract gem packages to +options+

Public Class Methods

new() click to toggle source
# File lib/rubygems/comparator/gemfile_comparator.rb, line 16
def initialize
  expect(:packages)
end

Public Instance Methods

compare(packages, report, options = {}) click to toggle source

Compare Gemfiles using gem's packages and write the changes to the report

# File lib/rubygems/comparator/gemfile_comparator.rb, line 24
def compare(packages, report, options = {})
  info 'Checking Gemfiles for dependencies...'
  return report if options[:param] && options[:param] != 'gemfiles'

  @packages = packages
  all_same = true

  # Check Gemfiles from older versions to newer
  packages.each_with_index do |pkg, index|
    unpacked_gem_dirs[@packages[index].spec.version] = extract_gem(pkg, options[:output])
    next if index == 0

    prev_gemfile = File.join(unpacked_gem_dirs[@packages[index-1].spec.version], 'Gemfile')
    curr_gemfile = File.join(unpacked_gem_dirs[@packages[index].spec.version], 'Gemfile')

    vers = "#{@packages[index-1].spec.version}->#{@packages[index].spec.version}"
    report['gemfiles'][vers].set_header "#{Rainbow(packages[index-1].spec.version).cyan}->" +
                                        "#{Rainbow(packages[index].spec.version).cyan}:"

    added, deleted, updated = compare_gemfiles(prev_gemfile, curr_gemfile)

    report['gemfiles'][vers]['added'].section do
      set_header '* Added:'
      puts added.map { |x| "#{x.name} #{x.requirements_list}" } unless added.empty?
    end
    report['gemfiles'][vers]['deleted'].section do
      set_header '* Deleted'
      puts deleted.map { |x| "#{x.name} #{x.requirements_list}" } unless deleted.empty?
    end
    report['gemfiles'][vers]['updated'].section do
      set_header '* Updated'
      puts updated  unless updated.empty?
    end
    all_same = false if !added.empty? || !deleted.empty?
  end
  if all_same && options[:log_all]
    report['gemfiles'].set_header "#{same} Gemfiles:"
    gemfile = File.join(unpacked_gem_dirs[@packages[1].spec.version], 'Gemfile')
    if File.exist? gemfile
      deps = gemfile_deps(gemfile)
      deps = '[]' if deps.empty?
      report['gemfiles'] << deps
    else
      report['gemfiles'] << 'No Gemfiles'
    end
  elsif !all_same
    report['gemfiles'].set_header "#{different} Gemfile dependencies"
  end

  report
end

Private Instance Methods

compare_gemfiles(prev_gemfile, curr_gemfile) click to toggle source

Compare two Gemfiles for dependencies

Return [added, deleted, updated] deps

# File lib/rubygems/comparator/gemfile_comparator.rb, line 93
def compare_gemfiles(prev_gemfile, curr_gemfile)
  prev_deps = gemfile_deps(prev_gemfile)
  curr_deps = gemfile_deps(curr_gemfile)
  added = curr_deps - prev_deps
  deleted = prev_deps - curr_deps

  split_dependencies(added, deleted)
end
gemfile_deps(gemfile) click to toggle source

Get the Gemfile dependencies from gemfile

# File lib/rubygems/comparator/gemfile_comparator.rb, line 105
def gemfile_deps(gemfile)
  if File.exist?(gemfile)
    parse_gemfile(gemfile).dependencies
  else
    []
  end
end
parse_gemfile(gemfile) click to toggle source

Parse gemfile using Gemnasium::Parser

Return Gemnasium::Parser::Gemfile

# File lib/rubygems/comparator/gemfile_comparator.rb, line 118
def parse_gemfile(gemfile)
  Gemnasium::Parser.gemfile File.open(gemfile).read
end
split_dependencies(added, deleted) click to toggle source

Find updated dependencies between added and deleted deps and move them out to updated.

Return [added, deleted, updated] deps

# File lib/rubygems/comparator/gemfile_comparator.rb, line 128
def split_dependencies(added, deleted)
  updated = []
  added.dup.each do |ad|
    deleted.dup.each do |dd|
      if ad.name == dd.name && ad.type == dd.type
        unless ad.requirements_list == dd.requirements_list
          updated << "#{ad.name} " +
                     "from: #{dd.requirements_list} " +
                     "to: #{ad.requirements_list}"
        end
        added.delete ad
        deleted.delete dd
      end
    end
  end
  [added, deleted, updated]
end
unpacked_gem_dirs() click to toggle source

Access @unpacked_gem_dirs hash that stores paths to the unpacked gem dirs

Keys of the hash are gem's versions

# File lib/rubygems/comparator/gemfile_comparator.rb, line 84
def unpacked_gem_dirs
  @unpacked_gem_dirs ||= {}
end