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
