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