Paludis Logo Introduction Examples
Bugs, Requests, Support C++ (core)
Overview Ruby (bindings)
FAQ Python (bindings)
Clients  
Configuration  
API  

example_dep_tree.rb

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.

00001 #!/usr/bin/ruby
00002 # vim: set sw=4 sts=4 et tw=100 :
00003 
00004 =begin description
00005 This example demonstrates how to handle dependency specs. It looks through
00006 all installed packages, and picks out any package whose dependencies include
00007 'app-arch/unzip', or whose fetchable files includes any with a '.zip'
00008 extension.
00009 =end
00010 
00011 require 'Paludis'
00012 require 'example_command_line'
00013 
00014 include Paludis
00015 
00016 # Collect dependencies upon 'app-arch/unzip' and store them in our results
00017 # table.
00018 def collect_dependencies env, id, spec, results, recursing_sets = {}
00019     # We need to handle every type that could be in a dependency heirarchy.
00020     if spec.instance_of? AllDepSpec
00021         # For an AllDepSpec, just collect all of our children
00022         spec.each do | child |
00023             collect_dependencies(env, id, child, results, recursing_sets)
00024         end
00025 
00026     elsif spec.instance_of? AnyDepSpec
00027         # Same for an AnyDepSpec
00028         spec.each do | child |
00029             collect_dependencies(env, id, child, results, recursing_sets)
00030         end
00031 
00032     elsif spec.instance_of? ConditionalDepSpec
00033         # Was this condition satisfied when we built this package?
00034         if spec.condition_met?
00035             spec.each do | child |
00036                 collect_dependencies(env, id, child, results, recursing_sets)
00037             end
00038         end
00039 
00040     elsif spec.instance_of? PackageDepSpec
00041         # spec.package may be a zero pointer if it's a wildcarded dep.
00042         if spec.package and spec.package == "app-arch/unzip"
00043             results[id.to_s][:has_dep] = true
00044         end
00045 
00046     elsif spec.instance_of? NamedSetDepSpec
00047         # For named set specs, we visit the set
00048         set = env.set(spec.name())
00049 
00050         # First complication: we might have a name referring to a set that
00051         # doesn't exist.
00052         if ! set
00053             Log.instance.message(LogLevel::Warning, "Unknown set '" + spec.name() + "'")
00054             return
00055         end
00056 
00057         # Second complication: we need to handle sets that contain themselves.
00058         # Although this shouldn't happen, user-defined sets can be made to
00059         # include themselves, possibly with other sets inbetween (a includes b
00060         # includes a).
00061         if recursing_sets[set.name()]
00062             Log.instance.message(LogLevel::Warning, "Recursively defined set '" + spec.name() + "'")
00063             return
00064         end
00065 
00066         recursing_sets[set.name()] = true
00067         collect_dependencies(env, id, child, results, recursing_sets)
00068         recursing_sets.delete(set.name())
00069 
00070     elsif spec.instance_of? BlockDepSpec
00071         # Do nothing
00072 
00073     elsif spec.instance_of? DependencyLabelsDepSpec
00074         # Do nothing
00075 
00076     else
00077         raise TypeError, "Got unexpected type '#{spec.class}'"
00078     end
00079 end
00080 
00081 # Collect files with extension '.zip' and store them in our results table.
00082 def collect_extensions env, id, spec, results, recursing_sets = {}
00083     # We need to handle every type that could be in a fetchable URI heirarchy.
00084     if spec.instance_of? AllDepSpec
00085         # For an AllDepSpec, just collect all of our children
00086         spec.each do | child |
00087             collect_extensions(env, id, child, results, recursing_sets)
00088         end
00089 
00090     elsif spec.instance_of? ConditionalDepSpec
00091         # Was this condition satisfied when we built this package?
00092         if spec.condition_met?
00093             spec.each do | child |
00094                 collect_extensions(env, id, child, results, recursing_sets)
00095             end
00096         end
00097 
00098     elsif spec.instance_of? FetchableURIDepSpec
00099         # We need to be careful not to assume that the filename has an
00100         # extension.
00101         if spec.filename[%r/\.zip$/]
00102             results[id.to_s][:has_ext] = true
00103         end
00104 
00105     elsif spec.instance_of? URILabelsDepSpec
00106         # Do nothing
00107 
00108     else
00109         raise TypeError, "Got unexpected type '#{spec.class}'"
00110     end
00111 
00112 end
00113 
00114 # We start with an Environment, respecting the user's '--environment' choice.
00115 env = EnvironmentFactory.instance.create(ExampleCommandLine.instance.environment)
00116 
00117 # Fetch package IDs for all installed packages.
00118 ids = env[Selection::AllVersionsSorted.new(
00119     Generator::All.new | Filter::InstalledAtRoot.new("/"))]
00120 
00121 # Our results table, mapping the ID to { :has_dep => ?, :has_ext => ? }
00122 results = { }
00123 
00124 # For each ID:
00125 ids.each do | id |
00126     # Make a default result for this ID.
00127     results[id.to_s] = { :has_dep => false, :has_ext => false }
00128 
00129     # IDs can potentially have four dependency-related keys. Each of thse keys
00130     # may return nil. If it doesn't, collect 'app-arch/unzip' dependencies.
00131     [ :build_dependencies_key, :run_dependencies_key, :post_dependencies_key ].each do | key |
00132         if id.send(key)
00133             collect_dependencies(env, id, id.send(key).parse_value, results)
00134         end
00135     end
00136 
00137     # And the same for '.zip' file extensions
00138     if id.fetches_key
00139         collect_extensions(env, id, id.fetches_key.parse_value, results)
00140     end
00141 end
00142 
00143 # Display our results
00144 print "Package".ljust(60), "| ", "Dep".ljust(4), "| ", "Ext".ljust(4), "\n"
00145 print "-" * 60, "+", "-" * 5, "+", "-" * 5, "\n"
00146 results.keys.sort.each do | id |
00147     print id.ljust(60), "| ", (results[id][:has_dep] ? "yes" : "no").ljust(4), "| ",
00148         (results[id][:has_ext] ? "yes" : "no").ljust(4), "\n"
00149 end
00150 puts
00151