1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
#!/usr/bin/python3
# List all contributors to a series of git commits.
# Copyright(C) 2022 Darrick J. Wong, All Rights Reserved.
# Licensed under GPL 2.0 or later
import re
import subprocess
import io
import sys
import argparse
DEBUG = False
def backtick(args):
'''Generator function that yields lines of a program's stdout.'''
if DEBUG:
print(' '.join(args))
p = subprocess.Popen(args, stdout = subprocess.PIPE)
for line in io.TextIOWrapper(p.stdout, encoding="utf-8"):
yield line.strip()
def get_developers(revspec):
"""Return the address list generated from signed-off-by and
acked-by lines in the message.
"""
addr_list = ['[email protected]', '[email protected]']
tags = '%s|%s|%s|%s|%s|%s|%s|%s' % (
'signed-off-by',
'acked-by',
'cc',
'reviewed-by',
'reported-by',
'tested-by',
'suggested-by',
'reported-and-tested-by')
regex1 = r'^(%s):\s+(.+)$' % tags
regex2 = r'^(%s):\s+.+<(.+)>$' % tags
r1 = re.compile(regex1, re.I)
r2 = re.compile(regex2, re.I)
for output in backtick(['git', 'log', '--pretty=medium', revspec]):
m = r2.match(output)
if m:
addr_list.append(m.expand(r'\g<2>'))
continue
m = r1.match(output)
if m:
addr_list.append(m.expand(r'\g<2>'))
return set(addr_list)
def main():
parser = argparse.ArgumentParser(description = "List email addresses of contributors to a series of git commits.")
parser.add_argument("revisions", nargs = 1, \
help = "git revisions to process.")
parser.add_argument("--delimiter", type = str, default = '\n', \
help = "Separate each email address with this string.")
args = parser.parse_args()
contributors = get_developers(args.revisions[0])
print(args.delimiter.join(sorted(contributors)))
return 0
if __name__ == '__main__':
sys.exit(main())
|