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