lib/rubygems/comparator.rb in gem-compare-0.0.2 vs lib/rubygems/comparator.rb in gem-compare-0.0.3
- old
+ new
@@ -1,12 +1,14 @@
require 'tmpdir'
require 'rbconfig'
require 'rainbow'
+require 'curb'
+require 'json'
require 'rubygems/package'
require 'rubygems/dependency'
require 'rubygems/spec_fetcher'
-require 'rubygems/comparator/base'
+require 'rubygems/comparator/utils'
require 'rubygems/comparator/report'
require 'rubygems/comparator/spec_comparator'
require 'rubygems/comparator/file_list_comparator'
require 'rubygems/comparator/dependency_comparator'
require 'rubygems/comparator/gemfile_comparator'
@@ -15,21 +17,23 @@
# Gem::Comparator compares different version of the given
# gem. It can compare spec values as well as file lists or
# Gemfiles
class Gem::Comparator
- include Gem::Comparator::Base
+ include Gem::Comparator::Utils
attr_accessor :options, :report
VERSION = '0.0.2'
##
# Set the working dir and process options
#
# Creates temporal directory if the gem files shouldn't be kept
def initialize(options)
+ info "gem-compare in #{VERSION}"
+
unless options[:keep_all]
options[:output] = Dir.mktmpdir
end
if options[:param] && !param_exists?(options[:param])
@@ -38,10 +42,18 @@
if options[:no_color]
Rainbow.enabled = false
end
+ # Let's override platforms with the latest one if
+ # a platform has been specified via --platform
+ if options[:added_platform]
+ Gem.platforms = [Gem.platforms.last]
+ options[:platform] = Gem.platforms.last.to_s
+ info "Overriding platform to: #{options[:platform]}"
+ end
+
@options = options
# Results from the comparison
@report = Gem::Comparator::Report.new
end
@@ -50,31 +62,35 @@
# Compare versions
#
# Compares file lists, requirements, other meta data
def compare_versions(gem_name, versions)
- info "gem-compare in #{VERSION}"
# Expand versions (<=, >=, ~>) and sort them
versions = expand_versions(gem_name, versions)
error 'Only one version specified. Specify at lease two versions.' \
if versions.size == 1
+ # This should match the final versions that has been compared
+ @compared_versions = versions
+
versions.each do |version|
- download_gems? ? download_package(gem_name, version) : download_specification(gem_name, version)
+ download_gems? ?
+ get_package(gem_name, version) :
+ get_specification(gem_name, version)
end
- @report.set_header "Compared versions: #{versions}"
+ @report.set_header "Compared versions: #{@compared_versions}"
comparators = [SpecComparator,
FileListComparator,
DependencyComparator,
GemfileComparator]
comparators.each do |c|
comparator = c.new
- cmp = (c::COMPARES == :packages) ? gem_packages.values : gem_specs.values
+ cmp = (comparator.compares == :packages) ? gem_packages.values : gem_specs.values
@report = comparator.compare(cmp, @report, @options)
end
# Clean up
FileUtils.rm_rf options[:output] unless options[:keep_all]
@@ -93,13 +109,14 @@
# +gem_name+ versions that match the criteria
#
# Return list of expanded versions
def expand_versions(gem_name, versions)
- info 'Expanding versions...'
+ info "Expanding versions #{versions}..."
expanded = []
versions.each do |version|
+ version = latest_gem_version(gem_name) if version == '_'
if version =~ VERSION_REGEX
expanded << version
next
end
op, v = (version.scan /(>=|<=|~>|!=|>|<|=)\s*(.*)/).flatten
@@ -119,27 +136,51 @@
Gem::Version.new v
end.sort.map(&:to_s)
error 'No versions found.' if versions.size == 0
- info "Versions: #{versions}"
+ info "Expanded versions: #{versions}"
versions
end
+ def remote_gem_versions(gem_name)
+ client = Curl::Easy.new
+ client.url = "https://rubygems.org/api/v1/versions/#{gem_name}.json"
+ client.follow_location = true
+ client.http_get
+ json = JSON.parse(client.body_str)
+ gems = json.collect { |version| version['number'] }
+ info "Upstream versions: #{gems}"
+ gems
+ end
+
+ def latest_gem_version(gem_name)
+ remote_gem_versions(gem_name).map{ |v| Gem::Version.new v }.max.to_s
+ end
+
def gem_file_name(gem_name, version)
- "#{gem_name}-#{version}.gem"
+ if @options[:platform]
+ "#{gem_name}-#{version}-#{@options[:platform]}.gem"
+ else
+ "#{gem_name}-#{version}.gem"
+ end
end
- def download_package(gem_name, version)
+ def get_package(gem_name, version)
gem_file = gem_file_name(gem_name, version)
return gem_packages["#{gem_file}"] if gem_packages["#{gem_file}"]
find_downloaded_gem(gem_file)
return gem_packages["#{gem_file}"] if gem_packages["#{gem_file}"]
- spec, source = download_specification(gem_name, version)
+ download_package(gem_name, version)
+ end
+ def download_package(gem_name, version)
+ spec, source = get_specification(gem_name, version)
+ gem_file = gem_file_name(gem_name, spec.version.to_s)
+
Dir.chdir @options[:output] do
source.download spec
end
package = Gem::Package.new File.join(@options[:output], gem_file)
@@ -147,26 +188,48 @@
info "#{gem_file} downloaded."
package
end
- def download_specification(gem_name, version)
+ def get_specification(gem_name, version)
gem_file = gem_file_name(gem_name, version)
return gem_specs["#{gem_file}"] if gem_specs["#{gem_file}"]
find_downloaded_gem(gem_file)
return gem_specs["#{gem_file}"] if gem_specs["#{gem_file}"]
+ download_specification(gem_name, version)
+ end
+
+ def download_specification(gem_name, version)
dep = Gem::Dependency.new gem_name, version
specs_and_sources, _errors = Gem::SpecFetcher.fetcher.spec_for_dependency dep
spec, source = specs_and_sources.max_by { |s,| s.version }
error "Gem #{gem_name} in #{version} doesn't exist." if spec.nil?
+
+ fix_comparing_version(version, spec.version.to_s)
+ gem_file = gem_file_name(gem_name, spec.version.to_s)
+
gem_specs["#{gem_file}"] = spec
[spec, source]
end
+ ##
+ # Ensure the right version is referenced
+
+ def fix_comparing_version(version, spec_version)
+ if spec_version != version
+ @compared_versions.each do |v|
+ if v == version
+ @compared_versions[@compared_versions.index(version)] = spec_version
+ return
+ end
+ end
+ end
+ end
+
def find_downloaded_gem(gem_file)
if File.exist? File.join(@options[:output], gem_file)
info "#{gem_file} exists, using already downloaded file."
package = Gem::Package.new File.join(@options[:output], gem_file)
use_package(package)
@@ -182,10 +245,10 @@
gem_specs["#{gem_file}"] = package.spec
end
def download_gems?
return true if @options[:keep_all]
- @options[:param] ? SPEC_FILES_PARAMS.include?(@options[:param]) : true
+ @options[:param] ? !param_available_in_marshal?(@options[:param]) : true
end
def gem_packages
@gem_packages ||= {}
end