1#!/usr/bin/env python
2
3"""
4Greps and returns the first svn log entry containing a line matching the regular
5expression pattern passed as the only arg.
6
7Example:
8
9svn log -v | grep-svn-log.py '^   D.+why_are_you_missing.h$'
10"""
11
12import fileinput, re, sys, StringIO
13
14# Separator string for "svn log -v" output.
15separator = '-' * 72
16
17usage = """Usage: grep-svn-log.py line-pattern
18Example:
19    svn log -v | grep-svn-log.py '^   D.+why_are_you_missing.h'"""
20
21class 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
45def 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
75def 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
84if __name__ == '__main__':
85    main()
86