84 lines
2.3 KiB
Python
Executable File
84 lines
2.3 KiB
Python
Executable File
#!/usr/bin/python
|
|
#
|
|
# by Erik Osheim
|
|
#
|
|
# available under the GNU GPL version 2.
|
|
#
|
|
# This program is designed to provide analysis of patches or diff files.
|
|
|
|
import optparse
|
|
import re
|
|
import sys
|
|
|
|
# matches the diff stanza, which have no leading identifier
|
|
diff_re = re.compile('^[0-9a-zA-Z,]+$')
|
|
|
|
# analyze a particular patch, which is assumed to contain multiple files
|
|
def info(f, verbose=False):
|
|
paths = []
|
|
l = 0
|
|
first = True
|
|
for line in f:
|
|
if first:
|
|
if diff_re.match(line):
|
|
paths.append(['-', 0, 0, 0, 0])
|
|
first = False
|
|
|
|
if diff_re.match(line):
|
|
if not paths:
|
|
paths.append(['-', 0, 0, 0, 0])
|
|
paths[-1][1] += 1
|
|
elif line.startswith('diff'):
|
|
path = line.split()[-1]
|
|
l = max(l, len(path))
|
|
paths.append([path, 0, 0, 0, 0])
|
|
elif line.startswith('Index'):
|
|
path = line.split()[1]
|
|
l = max(l, len(path))
|
|
paths.append([path, 0, 0, 0, 0])
|
|
elif line.startswith('---') or line.startswith('+++') or line.startswith('='):
|
|
pass
|
|
elif line.startswith('@@'):
|
|
paths[-1][1] += 1
|
|
elif line.startswith('+') or line.startswith('>'):
|
|
paths[-1][2] += 1
|
|
paths[-1][3] += 1
|
|
elif line.startswith('-') or line.startswith('<'):
|
|
paths[-1][2] -= 1
|
|
paths[-1][4] += 1
|
|
|
|
if len(paths) != 1:
|
|
title = '%d paths' % len(paths)
|
|
else:
|
|
title = '1 path'
|
|
|
|
if verbose:
|
|
title = 'TOTAL ' + title
|
|
else:
|
|
l = len(title)
|
|
|
|
totals = [0, 0, 0, 0]
|
|
for info in paths:
|
|
for i in range(0, 4):
|
|
totals[i] += info[i + 1]
|
|
|
|
lens = [len(str(n)) + 1 for n in totals[:2]]
|
|
fmt = '%%-%ds %%%dd groups, %%+%dd lines (+%%d -%%d)' % tuple([l] + lens)
|
|
for info in paths:
|
|
if verbose:
|
|
print fmt % tuple(info)
|
|
|
|
print fmt % tuple([title] + totals)
|
|
|
|
if __name__ == "__main__":
|
|
op = optparse.OptionParser()
|
|
op.add_option('-v', '--verbose', dest='verbose', action='store_true')
|
|
|
|
opts, args = op.parse_args()
|
|
|
|
if args:
|
|
for arg in args:
|
|
info(open(arg, 'r'), verbose=opts.verbose)
|
|
else:
|
|
info(sys.stdin, verbose=opts.verbose)
|