aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/api/ruby/Makefile.am1
-rw-r--r--doc/api/ruby/example_dep_tree.rb157
2 files changed, 158 insertions, 0 deletions
diff --git a/doc/api/ruby/Makefile.am b/doc/api/ruby/Makefile.am
index fd35bb5ee..ceab0be3e 100644
--- a/doc/api/ruby/Makefile.am
+++ b/doc/api/ruby/Makefile.am
@@ -28,6 +28,7 @@ examples = \
example_action.rb \
example_contents.rb \
example_dep_spec.rb \
+ example_dep_tree.rb \
example_query.rb \
example_version_operator.rb \
example_version_spec.rb
diff --git a/doc/api/ruby/example_dep_tree.rb b/doc/api/ruby/example_dep_tree.rb
new file mode 100644
index 000000000..01bd2cdc3
--- /dev/null
+++ b/doc/api/ruby/example_dep_tree.rb
@@ -0,0 +1,157 @@
+#!/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? UseDepSpec
+ # Was this use flag enabled (or, if we're inverse, disabled) when we
+ # built this package?
+ if env.query_use(spec.flag(), id) ^ spec.inverse?
+ 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 whildcarded 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? UseDepSpec
+ # Was this use flag enabled (or, if we're inverse, disabled) when we
+ # built this package?
+ if env.query_use(spec.flag(), id) ^ spec.inverse?
+ 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 = EnvironmentMaker.instance.make_from_spec(ExampleCommandLine.instance.environment)
+
+# Fetch package IDs for installed 'sys-apps/paludis'
+ids = env.package_database.query(
+ Query::SupportsInstalledAction.new, QueryOrder::OrderByVersion)
+
+# Our results table, mapping the ID to { :has_dep => ?, :has_ext => ? }
+results = { }
+
+# For each ID:
+ids.each do | id |
+ # Ignore old-style virtuals
+ next if id.virtual_for_key
+
+ # 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,
+ :suggested_dependencies_key ].each do | key |
+ if id.send(key)
+ collect_dependencies(env, id, id.send(key).value, results)
+ end
+ end
+
+ # And the same for '.zip' file extensions
+ if id.fetches_key
+ collect_extensions(env, id, id.fetches_key.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
+