forked from sympy/sympy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathauthors_update.py
executable file
·167 lines (140 loc) · 5.52 KB
/
authors_update.py
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A tool to generate AUTHORS. We started tracking authors before moving
to git, so we have to do some manual rearrangement of the git history
authors in order to get the order in AUTHORS. bin/mailmap_update.py
should be run before committing the results.
"""
from __future__ import unicode_literals
from __future__ import print_function
import codecs
import sys
import os
if sys.version_info < (3, 7):
sys.exit("This script requires Python 3.7 or newer")
from subprocess import run, PIPE
from sympy.external.importtools import version_tuple
from collections import OrderedDict
def red(text):
return "\033[31m%s\033[0m" % text
def yellow(text):
return "\033[33m%s\033[0m" % text
def green(text):
return "\033[32m%s\033[0m" % text
# put sympy on the path
mailmap_update_path = os.path.abspath(__file__)
mailmap_update_dir = os.path.dirname(mailmap_update_path)
sympy_top = os.path.split(mailmap_update_dir)[0]
sympy_dir = os.path.join(sympy_top, 'sympy')
if os.path.isdir(sympy_dir):
sys.path.insert(0, sympy_top)
from sympy.utilities.misc import filldedent
# check git version
minimal = '1.8.4.2'
git_ver = run(['git', '--version'], stdout=PIPE, encoding='utf-8').stdout[12:]
if version_tuple(git_ver) < version_tuple(minimal):
print(yellow("Please use a git version >= %s" % minimal))
def author_name(line):
assert line.count("<") == line.count(">") == 1
assert line.endswith(">")
return line.split("<", 1)[0].strip()
def move(l, i1, i2, who):
x = l.pop(i1)
# this will fail if the .mailmap is not right
assert who == author_name(x), \
'%s was not found at line %i' % (who, i1)
l.insert(i2, x)
# find who git knows ahout
git_command = ["git", "log", "--topo-order", "--reverse", "--format=%aN <%aE>"]
git_people = run(git_command, stdout=PIPE, encoding='utf-8').stdout.strip().split("\n")
# remove duplicates, keeping the original order
git_people = list(OrderedDict.fromkeys(git_people))
# Do the few changes necessary in order to reproduce AUTHORS:
try:
move(git_people, 2, 0, 'Ondřej Čertík')
move(git_people, 42, 1, 'Fabian Pedregosa')
move(git_people, 22, 2, 'Jurjen N.E. Bos')
git_people.insert(4, "*Marc-Etienne M.Leveille <[email protected]>")
move(git_people, 10, 5, 'Brian Jorgensen')
git_people.insert(11, "*Ulrich Hecht <[email protected]>")
# this will fail if the .mailmap is not right
assert 'Kirill Smelkov' == author_name(git_people.pop(12)
), 'Kirill Smelkov was not found at line 12'
move(git_people, 12, 32, 'Sebastian Krämer')
move(git_people, 227, 35, 'Case Van Horsen')
git_people.insert(43, "*Dan <[email protected]>")
move(git_people, 57, 59, 'Aaron Meurer')
move(git_people, 58, 57, 'Andrew Docherty')
move(git_people, 67, 66, 'Chris Smith')
move(git_people, 79, 76, 'Kevin Goodsell')
git_people.insert(84, "*Chu-Ching Huang <[email protected]>")
move(git_people, 93, 92, 'James Pearson')
# this will fail if the .mailmap is not right
assert 'Sergey B Kirpichev' == author_name(git_people.pop(226)
), 'Sergey B Kirpichev was not found at line 226.'
index = git_people.index(
"azure-pipelines[bot] " +
"<azure-pipelines[bot]@users.noreply.github.com>")
git_people.pop(index)
index = git_people.index(
"whitesource-bolt-for-github[bot] " +
"<whitesource-bolt-for-github[bot]@users.noreply.github.com>")
git_people.pop(index)
except AssertionError as msg:
print(red(msg))
sys.exit(1)
# define new lines for the file
header = filldedent("""
All people who contributed to SymPy by sending at least a patch or
more (in the order of the date of their first contribution), except
those who explicitly didn't want to be mentioned. People with a * next
to their names are not found in the metadata of the git history. This
file is generated automatically by running `./bin/authors_update.py`.
""").lstrip()
fmt = """There are a total of {authors_count} authors."""
header_extra = fmt.format(authors_count=len(git_people))
lines = header.splitlines()
lines.append('')
lines.append(header_extra)
lines.append('')
lines.extend(git_people)
# compare to old lines and stop if no changes were made
old_lines = codecs.open(os.path.realpath(os.path.join(
__file__, os.path.pardir, os.path.pardir, "AUTHORS")),
"r", "utf-8").read().splitlines()
if old_lines == lines:
print(green('No changes made to AUTHORS.'))
sys.exit(0)
# check for new additions
new_authors = []
for i in sorted(set(lines) - set(old_lines)):
try:
author_name(i)
new_authors.append(i)
except AssertionError:
continue
# write the new file
with codecs.open(os.path.realpath(os.path.join(
__file__, os.path.pardir, os.path.pardir, "AUTHORS")),
"w", "utf-8") as fd:
fd.write('\n'.join(lines))
fd.write('\n')
# warn about additions
if new_authors:
print(yellow(filldedent("""
The following authors were added to AUTHORS.
If mailmap_update.py has already been run and
each author appears as desired and is not a
duplicate of some other author, then the
changes can be committed. Otherwise, see
.mailmap for instructions on how to change
an author's entry.""")))
print()
for i in sorted(new_authors, key=lambda x: x.lower()):
print('\t%s' % i)
else:
print(yellow("The AUTHORS file was updated."))
print(red("Changes were made in the authors file"))
run(['git', 'diff']) # Show the changes
sys.exit(1)