~abentley/bzrtools/bzrtools.dev

0.1.32 by Michael Ellerman
Add Diffstat class to do diffstat internally.
1
#!/usr/bin/python
2
0.1.33 by Michael Ellerman
Rename Diffstat to DiffStat, looks better :)
3
class DiffStat(object):
0.1.32 by Michael Ellerman
Add Diffstat class to do diffstat internally.
4
    def __init__(self, lines):
5
        self.maxname = 0
6
        self.maxtotal = 0
7
        self.total_adds = 0
8
        self.total_removes = 0
9
        self.stats = {}
10
        self.__parse(lines)
11
12
    def __parse(self, lines):
13
        import string
14
        adds = 0
15
        removes = 0
16
        current = None
17
18
        for line in lines:
19
            if line.startswith('+') and not line.startswith('+++'):
20
                adds += 1
21
            elif line.startswith('-') and not line.startswith('---'):
22
                removes += 1
0.1.34 by Michael Ellerman
Make DiffStat work with bzr diff output :}
23
            elif line.startswith('=== '):
0.1.32 by Michael Ellerman
Add Diffstat class to do diffstat internally.
24
                self.__add_stats(current, adds, removes)
25
26
                adds = 0
27
                removes = 0
28
                context = 0
0.1.34 by Michael Ellerman
Make DiffStat work with bzr diff output :}
29
                current = None
30
            elif line.startswith('--- ') and current is None:
31
                current = line[4:].strip()
0.1.32 by Michael Ellerman
Add Diffstat class to do diffstat internally.
32
33
        self.__add_stats(current, adds, removes)
34
35
    class Filestat:
36
        def __init__(self):
37
            self.adds = 0
38
            self.removes = 0
39
            self.total = 0
40
41
    def __add_stats(self, file, adds, removes):
42
        if file is None:
43
            return
44
        elif file in self.stats:
45
            fstat = self.stats[file]
46
        else:
47
            fstat = self.Filestat()
48
49
        fstat.adds += adds
50
        fstat.removes += removes
51
        fstat.total = adds + removes
52
        self.stats[file] = fstat
53
54
        self.maxname = max(self.maxname, len(file))
55
        self.maxtotal = max(self.maxtotal, fstat.total)
56
        self.total_adds += adds
57
        self.total_removes += removes
58
59
    def __str__(self):
60
        # Work out widths
61
        width = 78 - 5
62
        countwidth = len(str(self.maxtotal))
63
        graphwidth = width - countwidth - self.maxname
64
        factor = 1
65
296.1.1 by Dafydd Harries
Fix a bug in diffstat that causes an infinite loop on long filenames.
66
        # The graph width can be <= 0 if there is a modified file with a
296.1.2 by Dafydd Harries
Use a minimum graphwidth of 10.
67
        # filename longer than 'width'. Use a minimum of 10.
68
        if graphwidth < 10:
296.1.1 by Dafydd Harries
Fix a bug in diffstat that causes an infinite loop on long filenames.
69
            graphwidth = 10
70
0.1.32 by Michael Ellerman
Add Diffstat class to do diffstat internally.
71
        while (self.maxtotal / factor) > graphwidth:
72
            factor += 1
73
74
        s = ""
75
76
        for file, fstat in self.stats.iteritems():
77
            s += ' %-*s | %*.d ' % (self.maxname, file, countwidth, fstat.total)
78
79
            # If diffstat runs out of room it doesn't print anything, which
80
            # isn't very useful, so always print at least one + or 1
81
            s += '+' * max(fstat.adds / factor, 1)
82
            s += '-' * max(fstat.removes / factor, 1)
83
            s += '\n'
84
296.1.3 by Dafydd Harries
Fix typo (s/changes/changed/).
85
        s += ' %d files changed, %d insertions(+), %d deletions(-)' % \
0.1.32 by Michael Ellerman
Add Diffstat class to do diffstat internally.
86
                (len(self.stats), self.total_adds, self.total_removes)
87
        return s
88
89
if __name__ == '__main__':
90
    import sys
0.1.33 by Michael Ellerman
Rename Diffstat to DiffStat, looks better :)
91
    ds = DiffStat(sys.stdin.readlines())
0.1.32 by Michael Ellerman
Add Diffstat class to do diffstat internally.
92
    print ds