#!/usr/local/bin/ruby # # NAME # portquery # # SYNOPSIS # portquery [-a] [-n] glob_name # # DESCRIPTION # Given a port name or glob, print all the dependencies of that port, # showing which are already installed. By default, a port is only # displayed once, even if it required by a number of other ports. Port # names are nested in an attempt to highlight dependencies. # # Command Arguments: # # -a Display all dependencies, even repeats for different ports # -n Only display ports which are not installed, or the version # installed is different to that required. # # NOTES # Depends on portupgrade being installed. # # If the INDEX.db file is not up-to-date, portquery will attempt to # update it. This will fail if you do not have write access to /usr/ports. # # Fields on INDEX file: # :pkgname, :origin, :prefix, :comment, :descr_file, # :maintainer, :categories, :build_depends, :run_depends, :www # # MODIFICATION HISTORY # Mnemonic Date Rel Who # portquery 20041127 1.0 mpw # Created. require 'pkgtools' require 'optparse' require 'ostruct' class OptParse # # Return a structure describing the options. # def self.parse(args) # The options specified on the command line will be collected in *options*. # We set default values here. options = OpenStruct.new options.all = false options.uninstalled_only = false opts = OptionParser.new do |opts| opts.banner = "Usage: portquery [options] glob_name" opts.separator "" opts.separator "Specific options:" opts.on("-a", "--all", "Display all dependencies, even repeats") do |a| options.all = a end opts.on("-n", "--not-installed", "Display only required ports that are not installed") do |n| options.uninstalled_only = n end opts.separator "" opts.separator "Common options:" # No argument, shows at tail. This will print an options summary. opts.on_tail("-h", "--help", "Show this message") do puts opts exit end end opts.parse!(args) options end # parse() end def printdeps(depth,portinfo,pkg_array,known,opts) portinfo.all_depends.map do |x| dependent_port = $portsdb.port(x) portname = dependent_port.pkgname.to_s if not opts.all and known.member?(portname) next end name = sprintf("%-30s ", " "*depth+portname) known.push(portname) if pkg_array.member?(portname) if not opts.uninstalled_only print "#{name}(installed)\n" end else # if version required is not installed, is some other version? port_stub = portname.slice(0,portname.rindex("-")) pkg_array.each { |n| if n.slice(0,n.rindex("-")) == port_stub name = "#{name}(but version #{n} is installed)" break end } print "#{name}\n" end printdeps(depth+1,dependent_port,pkg_array,known,opts) end end # no arguments, do nothing if ARGV.length == 0 exit() end # parse command line options begin options = OptParse.parse(ARGV) rescue OptionParser::InvalidOption => e print e.message.capitalize+"\n" exit end # load pkgtools.conf settings load_config # create pattern from command argument (port name or glob) begin pattern = parse_pattern(ARGV[0]) rescue RegexpError => e warning_message e.message.capitalize end # get array of installed packages pkg_array = $pkgdb.installed_pkgs() known = Array::new # run through ports matching glob $portsdb.glob(pattern) do |portinfo| print "#{portinfo.pkgname} requires:\n" printdeps(1,portinfo,pkg_array,known,options) known = Array::new end