Created
March 1, 2010 17:02
-
-
Save jrabbit/318556 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# This program reads a directory containing Fink package descriptions | |
# and generates a graph of the dependencies among the packages. The | |
# graph is in the DOT language and can be displayed by Graphviz. | |
# The pydot and pyparsing modules must be installed. | |
# Version 1.0 | |
# Written by Trevor Harmon <[email protected]> | |
# License: GPL - http://www.gnu.org/copyleft/gpl.html | |
import sys, os | |
from string import * | |
from pydot import * | |
packages = 0 | |
multiline_deps = 0 | |
graph = Dot() | |
# Reads the given file (which is assumed to be a valid Fink package description) | |
# and returns a dictionary containing the package name ('package') and an array | |
# of dependencies ('dependencies') as defined in the file. | |
def get_package_info(filename): | |
global multiline_deps | |
# Read the file | |
infile = open(filename, 'r') | |
inlines = infile.readlines() | |
package = None; | |
dependencies = None; | |
# Walk through the file line by line | |
for line in inlines: | |
# Check for package name definition | |
if line.startswith('Package:'): | |
# Strip out everything but the name | |
package = line[len('Package:'):].lower().strip() | |
# If this package contains %n, then it must be a split-off. Skip it. | |
if package.find('%n') == -1: | |
# Strip out everything after (and including) the % symbol. This is to handle | |
# packages defined like "svn-swig-pm%type_pkg[perl]" | |
package = package.split('%')[0] | |
# Check for dependency definitions | |
if line.startswith('Depends:'): | |
# We don't handle multi-line dependencies (yet). Abort. | |
if line.find('<<') >= 0: | |
multiline_deps += 1 | |
return None | |
# Convert the dependency list into an array of dependencies | |
deps = line[len('Depends:'):].strip().split(',') | |
dependencies = [] | |
for dep in deps: | |
# Ignore everything after (and including) the first whitespace | |
dep = dep.lower().split() | |
# Make sure the dependency actually was defined and is not just whitespace | |
if len(dep) > 0: | |
# Do percent expansion | |
dep[0] = dep[0].replace('%n', package) | |
# Strip out everything after (and including) the % symbol. This is to handle | |
# packages defined like "svn-swig-pm%type_pkg[perl]" | |
dep[0] = dep[0].split('%')[0] | |
# Add the dependency to the array | |
dependencies.append(dep[0]) | |
# We're done; quit now to avoid picking up splitoffs | |
return {'package' : package, 'dependencies' : dependencies} | |
# No dependencies were found | |
return {'package' : package, 'dependencies' : dependencies} | |
# Retrieves the name and dependency information in the given Fink package | |
# description and adds it to the PyDOT graph instance. | |
def add_package_to_graph(filename): | |
info = get_package_info(filename) | |
if info != None: | |
global packages; | |
packages += 1 | |
# Add the package name as a node in the graph | |
graph.add_node(Node(info['package'])) | |
# Add each dependency as an edge in the graph | |
deps = info['dependencies'] | |
if deps != None: | |
for dep in deps: | |
graph.add_edge(Edge(info['package'], dep)) | |
# Searches for all .info files in the given directory and adds them to the graph. | |
def add_directory_to_graph(directory): | |
if os.path.isdir(sys.argv[1]): | |
# Remove the trailing slash | |
if directory.endswith('/'): | |
directory = rstrip(directory, '/') | |
print 'Parsing', directory | |
# Search for all files in the given directory and clean each one | |
for root, dirs, files in os.walk(directory): | |
for filename in files: | |
if filename.endswith('.info'): | |
add_package_to_graph(root + '/' + filename) | |
else: | |
print 'Error:', directory, 'is not a directory.' | |
if len(sys.argv) < 2: | |
print 'Usage: fink-dep-graph <directory> [directory2, directory3, ...]' | |
else: | |
print 'Parsing package descriptions...' | |
outfile = 'fink-dependencies.dot'; | |
for directory in sys.argv[1:]: | |
add_directory_to_graph(directory) | |
print 'Found', packages, 'packages. (Split-offs are ignored.)' | |
if multiline_deps > 0: | |
print 'Skipped', multiline_deps, 'packages due to multi-line dependency declarations, which are not supported in this version.' | |
graph.write(outfile) | |
print 'Wrote dependency graph to', outfile |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment