#!/usr/bin/ruby
####################################################################
# depends.rb
#
# Usage: ./depends.rb debian-package [recursion level]
#    [debian-package]  any debian package you want to start with
#    [recursion level] how deeply you wish to search (defaults to 2)
#      Note- Recursions greater than 2 tend to produce very large 
#            data sets and "scatter" graphs of limited use
#
# Scrubs your local debian APT cache to determine dependencies
# up to a specified recursion level
# 
# 'apt-cache' already has a '-dotty' command, but it dumps the entire
# dependency tree. For large packages like 'gnome' or 'xserver-xorg' 
# the data are unusable and the graphs (if they can be created) are 
# large blotches of black lines. 
#
# The output of this program produces a reduced set to inspect each in turn
#
####################################################################
# To Do:
#   One idea is to produce separate sub graphs with small recursion
#     depth for each sub-level, so you could view the theire tree
#     in a series of plots rather than one giant graph.
####################################################################
# 04/30/07 - First release
####################################################################
# Copyright 2007 Jesse Caulfield - jmc at kbg dot ch
####################################################################
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
####################################################################


# Notes: In Ruby
# ARGV = $*
# Pattern matching: $1, $2, etc are automatically populated

############################################################
# We must have a starting package
if !ARGV[0] then
  puts "usage: my.rb package"
 exit 1
else
  package = ARGV[0]
end

if !ARGV[1] then
  Recursion = 2
else
  Recursion = ARGV[1]
end

############################################################
# Get the package size - not used yet
def aptSize(package)
#  print "<aptSize>"
  pinfo = %x[apt-cache show #{package} |grep ^Size]
  pattern = /Size: ([0-9]+)/
  pinfo.chomp!.match(pattern)
  size = $1
#  print "</aptSize>\n"
end

############################################################
# This is the function we recursively call 
def depends(package, level)

  # Get the apt-cache data into an array
  depackage =  %x[apt-cache depends #{package}]

  # Process each element of the returned array
  depackage.each { |depack|

    # each line looks like "Depends: gnome-screensaver"
    pattern = /Depends: ([A-Za-z-].+)/

    # strip the line's crlf & capture the package string
    sptemp = "#{depack}"
    sptemp.chomp!

    # Debug - print the line we're looking at
#    puts "working on #{sptemp}"

    # Execute the pattern match and assign the matched value to string sp
    if sp = depack.chomp!.match(pattern)
      spack = "#{$1}"

      # Create an indent for pretty printing
      spaces = " " * 2 * level.to_i

      # Find out how big this package is
      # size = aptSize("#{spack}")

      ##############################################################
      # Skip all library entries - they only introduce messiness to 
      ##############################################################
      if spack.match(/^lib/)
        # no-op
      else

        # Translate - to _, remove .
        

        #######################################################
        # Print a link line for the item we're working on     #
        # We must translate "-" and "." to "_" for dotty      #
        puts "#{spaces}#{package.tr("-","_").tr(".","_")} -- #{spack.tr("-","_").tr(".","_")};"
        #######################################################

        # Go deeper if the depends didn't have a "|" and we're not 
        # too deep already
        if sp.pre_match !~ /\|/ && level.to_i < Recursion.to_i 
          depends("#{spack}", "#{level.next}")
        end

      end  

#      DEBUG - some pattern matching experiments in Ruby
#      levelsize[level]+= size.to_i
#      puts "#{level}#{spaces}#{$1}"
#      print "matched: ", sp[0], "\n"
#      print "pre    : (", sp.pre_match, ")\n"
#      print "post   : ", sp.post_match, "\n"
#      print "capture: ", $1, "\n"
#      print " " , $1 , "\n"

    end

  }

  #------ recursion 
end



############################################################
# main() Here is where the program starts
# Begin the Graph file
# Put our starting package in a red box. All others will be black ovals
print "
strict graph G {
  splines=true;
  maxiter=100;
  overlap=scale;

  #{package.tr("-","_").tr(".","_")} [shape=box, color=\"red\"];
"

# Begin a recursive search with level = 1
depends("#{package}",  1)

# End the graph file
puts "}"
############################################################ END OF LINE

