普通文本  |  152行  |  3.31 KB

#!/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