|  | #!/usr/bin/env python | 
|  | # vim: ts=2 sw=2 | 
|  |  | 
|  | import optparse | 
|  | import re | 
|  | import sys | 
|  |  | 
|  |  | 
|  | class Dependency: | 
|  | def __init__(self, tgt): | 
|  | self.tgt = tgt | 
|  | self.pos = "" | 
|  | self.prereqs = set() | 
|  | self.visit = 0 | 
|  |  | 
|  | def add(self, prereq): | 
|  | self.prereqs.add(prereq) | 
|  |  | 
|  |  | 
|  | class Dependencies: | 
|  | def __init__(self): | 
|  | self.lines = {} | 
|  | self.__visit = 0 | 
|  | self.count = 0 | 
|  |  | 
|  | def add(self, tgt, prereq): | 
|  | t = self.lines.get(tgt) | 
|  | if not t: | 
|  | t = Dependency(tgt) | 
|  | self.lines[tgt] = t | 
|  | p = self.lines.get(prereq) | 
|  | if not p: | 
|  | p = Dependency(prereq) | 
|  | self.lines[prereq] = p | 
|  | t.add(p) | 
|  | self.count = self.count + 1 | 
|  |  | 
|  | def setPos(self, tgt, pos): | 
|  | t = self.lines.get(tgt) | 
|  | if not t: | 
|  | t = Dependency(tgt) | 
|  | self.lines[tgt] = t | 
|  | t.pos = pos | 
|  |  | 
|  | def get(self, tgt): | 
|  | if self.lines.has_key(tgt): | 
|  | return self.lines[tgt] | 
|  | else: | 
|  | return None | 
|  |  | 
|  | def __iter__(self): | 
|  | return self.lines.iteritems() | 
|  |  | 
|  | def trace(self, tgt, prereq): | 
|  | self.__visit = self.__visit + 1 | 
|  | d = self.lines.get(tgt) | 
|  | if not d: | 
|  | return | 
|  | return self.__trace(d, prereq) | 
|  |  | 
|  | def __trace(self, d, prereq): | 
|  | if d.visit == self.__visit: | 
|  | return d.trace | 
|  | if d.tgt == prereq: | 
|  | return [ [ d ], ] | 
|  | d.visit = self.__visit | 
|  | result = [] | 
|  | for pre in d.prereqs: | 
|  | recursed = self.__trace(pre, prereq) | 
|  | for r in recursed: | 
|  | result.append([ d ] + r) | 
|  | d.trace = result | 
|  | return result | 
|  |  | 
|  | def help(): | 
|  | print "Commands:" | 
|  | print "  dep TARGET             Print the prerequisites for TARGET" | 
|  | print "  trace TARGET PREREQ    Print the paths from TARGET to PREREQ" | 
|  |  | 
|  |  | 
|  | def main(argv): | 
|  | opts = optparse.OptionParser() | 
|  | opts.add_option("-i", "--interactive", action="store_true", dest="interactive", | 
|  | help="Interactive mode") | 
|  | (options, args) = opts.parse_args() | 
|  |  | 
|  | deps = Dependencies() | 
|  |  | 
|  | filename = args[0] | 
|  | print "Reading %s" % filename | 
|  |  | 
|  | if True: | 
|  | f = open(filename) | 
|  | for line in f: | 
|  | line = line.strip() | 
|  | if len(line) > 0: | 
|  | if line[0] == '#': | 
|  | pos,tgt = line.rsplit(":", 1) | 
|  | pos = pos[1:].strip() | 
|  | tgt = tgt.strip() | 
|  | deps.setPos(tgt, pos) | 
|  | else: | 
|  | (tgt,prereq) = line.split(':', 1) | 
|  | tgt = tgt.strip() | 
|  | prereq = prereq.strip() | 
|  | deps.add(tgt, prereq) | 
|  | f.close() | 
|  |  | 
|  | print "Read %d dependencies. %d targets." % (deps.count, len(deps.lines)) | 
|  | while True: | 
|  | line = raw_input("target> ") | 
|  | if not line.strip(): | 
|  | continue | 
|  | split = line.split() | 
|  | cmd = split[0] | 
|  | if len(split) == 2 and cmd == "dep": | 
|  | tgt = split[1] | 
|  | d = deps.get(tgt) | 
|  | if d: | 
|  | for prereq in d.prereqs: | 
|  | print prereq.tgt | 
|  | elif len(split) == 3 and cmd == "trace": | 
|  | tgt = split[1] | 
|  | prereq = split[2] | 
|  | if False: | 
|  | print "from %s to %s" % (tgt, prereq) | 
|  | trace = deps.trace(tgt, prereq) | 
|  | if trace: | 
|  | width = 0 | 
|  | for g in trace: | 
|  | for t in g: | 
|  | if len(t.tgt) > width: | 
|  | width = len(t.tgt) | 
|  | for g in trace: | 
|  | for t in g: | 
|  | if t.pos: | 
|  | print t.tgt, " " * (width-len(t.tgt)), "  #", t.pos | 
|  | else: | 
|  | print t.tgt | 
|  | print | 
|  | else: | 
|  | help() | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | try: | 
|  | main(sys.argv) | 
|  | except KeyboardInterrupt: | 
|  | print | 
|  | except EOFError: | 
|  | print | 
|  |  |