Exheredludis/doc/api/ruby/example_dep_tree.rb
2011-06-12 00:20:27 +01:00

152 lines
5.1 KiB
Ruby

#!/usr/bin/ruby
# vim: set sw=4 sts=4 et tw=100 :
=begin description
This example demonstrates how to handle dependency specs. It looks through
all installed packages, and picks out any package whose dependencies include
'app-arch/unzip', or whose fetchable files includes any with a '.zip'
extension.
=end
require 'Paludis'
require 'example_command_line'
include Paludis
# Collect dependencies upon 'app-arch/unzip' and store them in our results
# table.
def collect_dependencies env, id, spec, results, recursing_sets = {}
# We need to handle every type that could be in a dependency heirarchy.
if spec.instance_of? AllDepSpec
# For an AllDepSpec, just collect all of our children
spec.each do | child |
collect_dependencies(env, id, child, results, recursing_sets)
end
elsif spec.instance_of? AnyDepSpec
# Same for an AnyDepSpec
spec.each do | child |
collect_dependencies(env, id, child, results, recursing_sets)
end
elsif spec.instance_of? ConditionalDepSpec
# Was this condition satisfied when we built this package?
if spec.condition_met?
spec.each do | child |
collect_dependencies(env, id, child, results, recursing_sets)
end
end
elsif spec.instance_of? PackageDepSpec
# spec.package may be a zero pointer if it's a wildcarded dep.
if spec.package and spec.package == "app-arch/unzip"
results[id.to_s][:has_dep] = true
end
elsif spec.instance_of? NamedSetDepSpec
# For named set specs, we visit the set
set = env.set(spec.name())
# First complication: we might have a name referring to a set that
# doesn't exist.
if ! set
Log.instance.message(LogLevel::Warning, "Unknown set '" + spec.name() + "'")
return
end
# Second complication: we need to handle sets that contain themselves.
# Although this shouldn't happen, user-defined sets can be made to
# include themselves, possibly with other sets inbetween (a includes b
# includes a).
if recursing_sets[set.name()]
Log.instance.message(LogLevel::Warning, "Recursively defined set '" + spec.name() + "'")
return
end
recursing_sets[set.name()] = true
collect_dependencies(env, id, child, results, recursing_sets)
recursing_sets.delete(set.name())
elsif spec.instance_of? BlockDepSpec
# Do nothing
elsif spec.instance_of? DependencyLabelsDepSpec
# Do nothing
else
raise TypeError, "Got unexpected type '#{spec.class}'"
end
end
# Collect files with extension '.zip' and store them in our results table.
def collect_extensions env, id, spec, results, recursing_sets = {}
# We need to handle every type that could be in a fetchable URI heirarchy.
if spec.instance_of? AllDepSpec
# For an AllDepSpec, just collect all of our children
spec.each do | child |
collect_extensions(env, id, child, results, recursing_sets)
end
elsif spec.instance_of? ConditionalDepSpec
# Was this condition satisfied when we built this package?
if spec.condition_met?
spec.each do | child |
collect_extensions(env, id, child, results, recursing_sets)
end
end
elsif spec.instance_of? FetchableURIDepSpec
# We need to be careful not to assume that the filename has an
# extension.
if spec.filename[%r/\.zip$/]
results[id.to_s][:has_ext] = true
end
elsif spec.instance_of? URILabelsDepSpec
# Do nothing
else
raise TypeError, "Got unexpected type '#{spec.class}'"
end
end
# We start with an Environment, respecting the user's '--environment' choice.
env = EnvironmentFactory.instance.create(ExampleCommandLine.instance.environment)
# Fetch package IDs for all installed packages.
ids = env[Selection::AllVersionsSorted.new(
Generator::All.new | Filter::InstalledAtRoot.new("/"))]
# Our results table, mapping the ID to { :has_dep => ?, :has_ext => ? }
results = { }
# For each ID:
ids.each do | id |
# Make a default result for this ID.
results[id.to_s] = { :has_dep => false, :has_ext => false }
# IDs can potentially have four dependency-related keys. Each of thse keys
# may return nil. If it doesn't, collect 'app-arch/unzip' dependencies.
[ :build_dependencies_key, :run_dependencies_key, :post_dependencies_key ].each do | key |
if id.send(key)
collect_dependencies(env, id, id.send(key).parse_value, results)
end
end
# And the same for '.zip' file extensions
if id.fetches_key
collect_extensions(env, id, id.fetches_key.parse_value, results)
end
end
# Display our results
print "Package".ljust(60), "| ", "Dep".ljust(4), "| ", "Ext".ljust(4), "\n"
print "-" * 60, "+", "-" * 5, "+", "-" * 5, "\n"
results.keys.sort.each do | id |
print id.ljust(60), "| ", (results[id][:has_dep] ? "yes" : "no").ljust(4), "| ",
(results[id][:has_ext] ? "yes" : "no").ljust(4), "\n"
end
puts