Home | History | Annotate | Download | only in misc
      1 #!/usr/bin/env python
      2 
      3 """
      4 Greps and returns the first svn log entry containing a line matching the regular
      5 expression pattern passed as the only arg.
      6 
      7 Example:
      8 
      9 svn log -v | grep-svn-log.py '^   D.+why_are_you_missing.h$'
     10 """
     11 
     12 import fileinput, re, sys, StringIO
     13 
     14 # Separator string for "svn log -v" output.
     15 separator = '-' * 72
     16 
     17 usage = """Usage: grep-svn-log.py line-pattern
     18 Example:
     19     svn log -v | grep-svn-log.py '^   D.+why_are_you_missing.h'"""
     20 
     21 class Log(StringIO.StringIO):
     22     """Simple facade to keep track of the log content."""
     23     def __init__(self):
     24         self.reset()
     25     def add_line(self, a_line):
     26         """Add a line to the content, if there is a previous line, commit it."""
     27         global separator
     28         if self.prev_line != None:
     29             print >> self, self.prev_line
     30         self.prev_line = a_line
     31         self.separator_added = (a_line == separator)
     32     def del_line(self):
     33         """Forget about the previous line, do not commit it."""
     34         self.prev_line = None
     35     def reset(self):
     36         """Forget about the previous lines entered."""
     37         StringIO.StringIO.__init__(self)
     38         self.prev_line = None
     39     def finish(self):
     40         """Call this when you're finished with populating content."""
     41         if self.prev_line != None:
     42             print >> self, self.prev_line
     43         self.prev_line = None
     44 
     45 def grep(regexp):
     46     # The log content to be written out once a match is found.
     47     log = Log()
     48 
     49     LOOKING_FOR_MATCH = 0
     50     FOUND_LINE_MATCH = 1
     51     state = LOOKING_FOR_MATCH
     52 
     53     while 1:
     54         line = sys.stdin.readline()
     55         if not line:
     56             return
     57         line = line.splitlines()[0]
     58         if state == FOUND_LINE_MATCH:
     59             # At this state, we keep on accumulating lines until the separator
     60             # is encountered.  At which point, we can return the log content.
     61             if line == separator:
     62                 log.finish()
     63                 print log.getvalue()
     64                 return
     65             log.add_line(line)
     66 
     67         elif state == LOOKING_FOR_MATCH:
     68             if line == separator:
     69                 log.reset()
     70             log.add_line(line)
     71             # Update next state if necessary.
     72             if regexp.search(line):
     73                 state = FOUND_LINE_MATCH
     74 
     75 def main():
     76     if len(sys.argv) != 2:
     77         print usage
     78         sys.exit(0)
     79 
     80     regexp = re.compile(sys.argv[1])
     81     grep(regexp)
     82     sys.stdin.close()
     83 
     84 if __name__ == '__main__':
     85     main()
     86