Skip to content

Commit

Permalink
Merge pull request #210 from DimitriPapadopoulos/authors.py
Browse files Browse the repository at this point in the history
Update authors.py
  • Loading branch information
skjerns authored Jun 23, 2023
2 parents 7654b4c + 469c04f commit 77c05df
Showing 1 changed file with 78 additions and 32 deletions.
110 changes: 78 additions & 32 deletions util/authors.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#!/usr/bin/env python
# -*- encoding:utf-8 -*-
"""
git-authors [OPTIONS] REV1..REV2
List the authors who contributed within a given revision interval::
List the authors who contributed within a given revision interval.
python tools/authors.py REV1..REV2
`REVx` being a commit hash.
To change the name mapping, edit .mailmap on the top-level of the
repository.
"""
# Author: Pauli Virtanen <pav@iki.fi>. This script is in the public domain.
Expand All @@ -11,25 +17,20 @@
import re
import sys
import os
import io
import subprocess
import collections


from scipy._lib.six import u, PY3
if PY3:
stdout_b = sys.stdout.buffer
else:
stdout_b = sys.stdout


NAME_MAP = {
u('Helder'): u('Helder Oliveira'),
}
stdout_b = sys.stdout.buffer
MAILMAP_FILE = os.path.join(os.path.dirname(__file__), "..", ".mailmap")


def main():
p = optparse.OptionParser(__doc__.strip())
p.add_option("-d", "--debug", action="store_true",
help="print debug output")
p.add_option("-n", "--new", action="store_true",
help="print debug output")
options, args = p.parse_args()

if len(args) != 1:
Expand All @@ -40,36 +41,38 @@ def main():
except ValueError:
p.error("argument is not a revision range")

NAME_MAP = load_name_map(MAILMAP_FILE)

# Analyze log data
all_authors = set()
authors = set()
authors = collections.Counter()

def analyze_line(line, names, disp=False):
line = line.strip().decode('utf-8')

# Check the commit author name
m = re.match(u('^@@@([^@]*)@@@'), line)
m = re.match(u'^@@@([^@]*)@@@', line)
if m:
name = m.group(1)
line = line[m.end():]
name = NAME_MAP.get(name, name)
if disp:
if name not in names:
stdout_b.write((" - Author: %s\n" % name).encode('utf-8'))
names.add(name)
names.update((name,))

# Look for "thanks to" messages in the commit log
m = re.search(u(r'([Tt]hanks to|[Cc]ourtesy of) ([A-Z][A-Za-z]*? [A-Z][A-Za-z]*? [A-Z][A-Za-z]*|[A-Z][A-Za-z]*? [A-Z]\. [A-Z][A-Za-z]*|[A-Z][A-Za-z ]*? [A-Z][A-Za-z]*|[a-z0-9]+)($|\.| )'), line)
m = re.search(r'([Tt]hanks to|[Cc]ourtesy of|Co-authored-by:) ([A-Z][A-Za-z]*? [A-Z][A-Za-z]*? [A-Z][A-Za-z]*|[A-Z][A-Za-z]*? [A-Z]\. [A-Z][A-Za-z]*|[A-Z][A-Za-z ]*? [A-Z][A-Za-z]*|[a-z0-9]+)($|\.| )', line)
if m:
name = m.group(2)
if name not in (u('this'),):
if name not in (u'this',):
if disp:
stdout_b.write(" - Log : %s\n" % line.strip().encode('utf-8'))
name = NAME_MAP.get(name, name)
names.add(name)
names.update((name,))

line = line[m.end():].strip()
line = re.sub(u(r'^(and|, and|, ) '), u('Thanks to '), line)
line = re.sub(r'^(and|, and|, ) ', u'Thanks to ', line)
analyze_line(line.encode('utf-8'), names)

# Find all authors before the named range
Expand All @@ -84,24 +87,39 @@ def analyze_line(line, names, disp=False):

# Sort
def name_key(fullname):
m = re.search(u(' [a-z ]*[A-Za-z-\']+$'), fullname)
m = re.search(u' [a-z ]*[A-Za-z-]+$', fullname)
if m:
forename = fullname[:m.start()].strip()
surname = fullname[m.start():].strip()
else:
forename = ""
surname = fullname.strip()
surname = surname.replace('\'', '')
if surname.startswith(u('van der ')):
if surname.startswith(u'van der '):
surname = surname[8:]
if surname.startswith(u('de ')):
if surname.startswith(u'de '):
surname = surname[3:]
if surname.startswith(u('von ')):
if surname.startswith(u'von '):
surname = surname[4:]
return (surname.lower(), forename.lower())

authors = list(authors)
authors.sort(key=name_key)
# generate set of all new authors
if vars(options)['new']:
new_authors = set(authors.keys()).difference(all_authors)
n_authors = list(new_authors)
n_authors.sort(key=name_key)
# Print some empty lines to separate
stdout_b.write(("\n\n").encode('utf-8'))
for author in n_authors:
stdout_b.write(("- %s\n" % author).encode('utf-8'))
# return for early exit so we only print new authors
return

try:
authors.pop('GitHub')
except KeyError:
pass
# Order by name. Could order by count with authors.most_common()
authors = sorted(authors.items(), key=lambda i: name_key(i[0]))

# Print
stdout_b.write(b"""
Expand All @@ -110,11 +128,14 @@ def name_key(fullname):
""")

for author in authors:
for author, count in authors:
# remove @ if only GH handle is available
author_clean = author.strip('@')

if author in all_authors:
stdout_b.write(("* %s\n" % author).encode('utf-8'))
stdout_b.write((f"* {author_clean} ({count})\n").encode('utf-8'))
else:
stdout_b.write(("* %s +\n" % author).encode('utf-8'))
stdout_b.write((f"* {author_clean} ({count}) +\n").encode('utf-8'))

stdout_b.write(("""
A total of %(count)d people contributed to this release.
Expand All @@ -123,8 +144,32 @@ def name_key(fullname):
""" % dict(count=len(authors))).encode('utf-8'))

stdout_b.write("\nNOTE: Check this list manually! It is automatically generated "
"and some names\n may be missing.\n")
stdout_b.write(("\nNOTE: Check this list manually! It is automatically generated "
"and some names\n may be missing.\n").encode('utf-8'))


def load_name_map(filename):
name_map = {}

with io.open(filename, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if line.startswith(u"#") or not line:
continue

m = re.match(r'^(.*?)\s*<(.*?)>(.*?)\s*<(.*?)>\s*$', line)
if not m:
print("Invalid line in .mailmap: '{!r}'".format(line), file=sys.stderr)
sys.exit(1)

new_name = m.group(1).strip()
old_name = m.group(3).strip()

if old_name and new_name:
name_map[old_name] = new_name

return name_map


#------------------------------------------------------------------------------
# Communicating with Git
Expand Down Expand Up @@ -182,6 +227,7 @@ def test(self, command, *a, **kw):
call=True, **kw)
return (ret == 0)


git = Cmd("git")

#------------------------------------------------------------------------------
Expand Down

0 comments on commit 77c05df

Please sign in to comment.