#!/usr/bin/env ruby
# vim: set sw=4 sts=4 et :
require 'Paludis'
require 'rubygems/source_info_cache'
require 'markaby'
require 'getoptlong'
include Paludis
master_repository_dir = '/var/empty'
write_cache_dir = '/var/empty'
repository_dir = '/var/paludis/repositories/gentoo'
Log.instance.log_level = LogLevel::Warning
Log.instance.program_name = $0
opts = GetoptLong.new(
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
[ '--log-level', GetoptLong::REQUIRED_ARGUMENT ],
[ '--master-repository-dir', GetoptLong::REQUIRED_ARGUMENT ],
[ '--repository-dir', GetoptLong::REQUIRED_ARGUMENT ],
[ '--write-cache-dir', GetoptLong::REQUIRED_ARGUMENT ]
)
opts.each do | opt, arg |
case opt
when '--help'
puts "Usage: " + $0 + " [options]"
puts
puts "Options:"
puts " --help Display a help message"
puts " --version Display program version"
puts
puts " --log-level level Set log level (debug, qa, warning, silent)"
puts " --repository-dir Use the specified location for the repository (default /var/paludis/repositories/gentoo"
puts " --master-repository-dir Use the specified location for the master repository"
puts " --write-cache-dir Use a subdirectory named for the repository name under the specified directory for repository write cache"
exit 0
when '--log-level'
case arg
when 'debug'
Paludis::Log.instance.log_level = Paludis::LogLevel::Debug
when 'qa'
Paludis::Log.instance.log_level = Paludis::LogLevel::Qa
when 'warning'
Paludis::Log.instance.log_level = Paludis::LogLevel::Warning
when 'silent'
Paludis::Log.instance.log_level = Paludis::LogLevel::Silent
else
puts "Bad --log-level value " + arg
exit 1
end
when '--write-cache-dir'
write_cache_dir = arg
when '--master-repository-dir'
master_repository_dir = arg
when '--repository-dir'
repository_dir = arg
end
end
$env = NoConfigEnvironment.new(repository_dir, write_cache_dir, master_repository_dir)
$db = $env.package_database
$repo_name = $env.main_repository.name
pids = $db.query(Query::Repository.new($repo_name), QueryOrder::BestVersionOnly)
$not_found = []
$equal = []
$higher = []
$lower = []
# Pretty Print a DepSpec
def pp_pspec(spec)
output = ''
if spec.kind_of? AllDepSpec
output+= ' ( '
spec.each do |child|
output+= pp_pspec(child)
end
output+= ' ) '
elsif spec.kind_of? AnyDepSpec
output+= ' || ( '
spec.each do |child|
output+= pp_pspec(child)
end
output+= ' ) '
elsif spec.kind_of? ConditionalDepSpec
output+= spec.condition
output+= ' ( '
spec.each do |child|
output+= pp_pspec(child)
end
output+= ' ) '
elsif spec.kind_of? PackageDepSpec
output += "#{spec.to_s} "
elsif spec.kind_of? BlockDepSpec
output+= ' !' + pp_pspec(spec.blocked_spec)
else
$stderr.puts "#{spec.class} is missing, fail."
end
return output
end
module Gem
class Requirement
# Helps to be able to read this in Dependency
attr_reader :requirements
end
class Dependency
# Create an array of PackageDepSpecs base on the name of gem
def paludis_array(db)
begin
qpn = db.fetch_unique_qualified_package_name(name.downcase)
rescue NoSuchPackageError
qpn = "gems/#{name}"
rescue Paludis::AmbiguousPackageNameError
qpn = "ambiguous/#{name}"
rescue Paludis::PackageNameLookupError
end
version_requirements.requirements.collect do |op, ver|
parse_user_package_dep_spec("#{op}#{qpn}-#{ver}", [])
end
end
end
end
# Given an array of Gems::Dependency, get an array of PacakgeDepSpec from them.
def gem_dep_list(deps, db)
deps.collect do |dep|
dep.paludis_array(db)
end.flatten
end
pids.each do |pid|
# We only care about packages that inherite gems.eclass
inherit = pid['INHERITED']
if !inherit.nil? && inherit.value.include?('gems')
specs = Gem::SourceInfoCache.search(/^#{pid.name.package}$/i)
if specs.empty?
$not_found << pid
else
# Gem::SourceInfoCache returns an array of Gem:Specification,
# we only care about the highest version
gemspec = specs.last
# Rely on paludis to do version comparisons
version = VersionSpec.new(gemspec.version.to_s)
# Gems don't have a revision, so remove it from the PackageID
pid_version = pid.version.remove_revision
entry = { :pid => pid, :gemspec => gemspec }
if version > pid_version
$higher << entry
elsif version == pid_version
$equal << entry
else
$lower << entry
end
end
end
end
module HideMarkaby
Markaby::Builder.set(:indent, 2)
mab = Markaby::Builder.new.xhtml_strict do
head do
title " #{$repo_name} rubygems comparison "
tag! :link, :href => 'compare_gems.css', :rel => 'stylesheet', :type => 'text/css'
end
body do
h1 " #{$repo_name} rubygems comparison "
unless $higher.empty?
h2 "Newer versions are available for the following packages"
dl do
$higher.each do |entry|
pid = entry[:pid]
gemspec = entry[:gemspec]
output = pid.to_s
# ebuilds can have more than 1 homepage, collect them
# this method is fragile.
homepages = []
i = 1
pid['HOMEPAGE'].value.each do |spec|
homepages << a.homepage("#{i}", :href=> spec)
i+=1
end
output += ' (' + homepages.join(', ') + ')'
dt { output }
dd do
p pid['DESCRIPTION'].value
table do
tr do
th ''
th 'Version'
th 'Dependencies'
end
tr do
td 'gentoo-x86'
td pid.version
td do
%w{build run post}.each do |key|
spec_text = pp_pspec(pid.send("#{key}_dependencies_key".to_sym).value)
unless ' ( ) ' == spec_text
text "#{key.capitalize}: #{spec_text}"
br
end
end
end
end
tr do
td 'rubygems'
td gemspec.version
td do
specs = gem_dep_list(gemspec.dependencies, $db)
specs.each do |spec|
case spec.package.category
when 'gems'
# If the category is gems, there is not an ebuild for this gem, so link
# to the gem's homepage
new_specs = Gem::SourceInfoCache.search(/^#{spec.package.package}$/i)
if new_specs.nil?
span.gems spec.to_s
else
a.gems spec.to_s, :href => new_specs.last.homepage
end
when 'ambiguous'
# Do nothing fancy if we had an ambiguous match
span.ambiguous spec.to_s
else
# Query for the spec we generated in the database
unless $db.query(Query::Matches.new(spec), QueryOrder::BestVersionOnly).empty?
# Our spec matches, we already have a high enough version
span.ok spec.to_s
else
# Link to the gem homepage, because we need to bump
new_pid = $db.query(Query::Package.new(spec.package), QueryOrder::BestVersionOnly)[0]
output=""
new_pid["HOMEPAGE"].value.each do |homepage_spec|
output << homepage_spec.to_s
break
end
a.bad_version spec.to_s, :href => output
end
end
end
end
end
end
end
end
end
end
unless $not_found.empty?
h2 "Packages not found in gems.rubyforge.org"
dl do
$not_found.each do |pid|
dt pid.to_s
dd pid['DESCRIPTION'].value
end
end
end
end
end
File.open($0.gsub(/\.rb$/, '.html'), 'w') do |out|
out.print mab.to_s
end
end