f8d165
#!/usr/bin/ruby
f8d165
f8d165
require 'rubygems/package'
f8d165
f8d165
module RubyGemsReq
f8d165
  module Helpers
f8d165
    # Expands '~>' and '!=' gem requirements.
f8d165
    def self.expand_requirement(requirements)
f8d165
      requirements.inject([]) do |output, r|
f8d165
        output.concat case r.first
f8d165
        when '~>'
f8d165
          expand_pessimistic_requirement(r)
f8d165
        when '!='
f8d165
          # If there is only the conflict requirement, we still need to depend
f8d165
          # on the specified gem.
f8d165
          if requirements.size == 1
f8d165
            Gem::Requirement.default.requirements
f8d165
          else
f8d165
            []
f8d165
          end
f8d165
        else
f8d165
          [r]
f8d165
        end
f8d165
      end.reject {|r| r.empty? }
f8d165
    end
f8d165
f8d165
    # Expands the pessimistic version operator '~>' into equivalent '>=' and
f8d165
    # '<' pair.
f8d165
    def self.expand_pessimistic_requirement(requirement)
f8d165
      next_version = Gem::Version.create(requirement.last).bump
f8d165
      return ['>=', requirement.last], ['<', next_version]
f8d165
    end
f8d165
f8d165
    # Converts Gem::Requirement into array of requirements strings compatible
f8d165
    # with RPM .spec file.
f8d165
    def self.requirement_versions_to_rpm(requirement)
f8d165
      self.expand_requirement(requirement.requirements).map do |op, version|
f8d165
        version == Gem::Version.new(0) ? "" : "#{op} #{version}"
f8d165
      end
f8d165
    end
f8d165
  end
f8d165
f8d165
  # Report RubyGems dependency, versioned if required.
f8d165
  def self.rubygems_dependency(specification)
f8d165
    Helpers::requirement_versions_to_rpm(specification.required_rubygems_version).each do |requirement|
f8d165
      dependency_string = "ruby(rubygems)"
f8d165
      dependency_string += " #{specification.required_rubygems_version}" if requirement&.length > 0
f8d165
      puts dependency_string
f8d165
    end
f8d165
  end
f8d165
f8d165
  # Report all gem dependencies including their version.
f8d165
  def self.gem_depenencies(specification)
f8d165
    specification.runtime_dependencies.each do |dependency|
f8d165
      dependency_strings = Helpers::requirement_versions_to_rpm(dependency.requirement).map do |requirement|
f8d165
        requirement_string = "rubygem(#{dependency.name})"
f8d165
        requirement_string += " #{requirement}" if requirement&.length > 0
f8d165
        requirement_string
f8d165
      end
f8d165
      dependency_string = dependency_strings.join(' with ')
f8d165
      dependency_string.prepend('(').concat(')') if dependency_strings.length > 1
f8d165
      puts dependency_string
f8d165
    end
f8d165
  end
f8d165
f8d165
  # Reports all requirements specified by all provided .gemspec files.
f8d165
  def self.requires
f8d165
    while filename = gets
f8d165
      filename.strip!
f8d165
      begin
f8d165
        specification = Gem::Specification.load filename
f8d165
f8d165
        rubygems_dependency(specification)
f8d165
        gem_depenencies(specification)
f8d165
      rescue => e
f8d165
        # Ignore all errors.
f8d165
      end
f8d165
    end
f8d165
  end
f8d165
end
f8d165
f8d165
if __FILE__ == $0
f8d165
  RubyGemsReq::requires
f8d165
end