110dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen#!/usr/bin/env python 210dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 310dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen""" 410dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny ChenGreps and returns the first svn log entry containing a line matching the regular 510dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chenexpression pattern passed as the only arg. 610dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 710dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny ChenExample: 810dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 910dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chensvn log -v | grep-svn-log.py '^ D.+why_are_you_missing.h$' 1010dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen""" 1110dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 1210dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chenimport fileinput, re, sys, StringIO 1310dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 1410dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen# Separator string for "svn log -v" output. 1510dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chenseparator = '-' * 72 1610dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 1710dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chenusage = """Usage: grep-svn-log.py line-pattern 1810dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny ChenExample: 1910dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen svn log -v | grep-svn-log.py '^ D.+why_are_you_missing.h'""" 2010dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 2110dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chenclass Log(StringIO.StringIO): 2210dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen """Simple facade to keep track of the log content.""" 2310dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen def __init__(self): 2410dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen self.reset() 2510dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen def add_line(self, a_line): 2610dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen """Add a line to the content, if there is a previous line, commit it.""" 2710dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen global separator 2810dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen if self.prev_line != None: 2910dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen print >> self, self.prev_line 3010dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen self.prev_line = a_line 3110dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen self.separator_added = (a_line == separator) 3210dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen def del_line(self): 3310dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen """Forget about the previous line, do not commit it.""" 3410dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen self.prev_line = None 3510dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen def reset(self): 3610dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen """Forget about the previous lines entered.""" 3710dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen StringIO.StringIO.__init__(self) 3810dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen self.prev_line = None 3910dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen def finish(self): 4010dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen """Call this when you're finished with populating content.""" 4110dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen if self.prev_line != None: 4210dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen print >> self, self.prev_line 4310dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen self.prev_line = None 4410dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 4510dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chendef grep(regexp): 4610dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen # The log content to be written out once a match is found. 4710dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen log = Log() 4810dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 4910dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen LOOKING_FOR_MATCH = 0 5010dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen FOUND_LINE_MATCH = 1 5110dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen state = LOOKING_FOR_MATCH 5210dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 5310dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen while 1: 5410dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen line = sys.stdin.readline() 5510dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen if not line: 5610dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen return 5710dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen line = line.splitlines()[0] 5810dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen if state == FOUND_LINE_MATCH: 5910dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen # At this state, we keep on accumulating lines until the separator 6010dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen # is encountered. At which point, we can return the log content. 6110dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen if line == separator: 62aa142bcacd9768bbd4fa83deed12b1accb6fd080Johnny Chen log.finish() 6310dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen print log.getvalue() 6410dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen return 6510dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen log.add_line(line) 6610dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 6710dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen elif state == LOOKING_FOR_MATCH: 6810dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen if line == separator: 6910dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen log.reset() 7010dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen log.add_line(line) 7110dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen # Update next state if necessary. 7210dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen if regexp.search(line): 7310dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen state = FOUND_LINE_MATCH 7410dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 7510dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chendef main(): 7610dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen if len(sys.argv) != 2: 7710dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen print usage 7810dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen sys.exit(0) 7910dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 8010dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen regexp = re.compile(sys.argv[1]) 8110dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen grep(regexp) 82aa142bcacd9768bbd4fa83deed12b1accb6fd080Johnny Chen sys.stdin.close() 8310dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen 8410dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chenif __name__ == '__main__': 8510dd7a4a70fe639b806e004bc0a0d6fb791279a3Johnny Chen main() 86