##// END OF EJS Templates
scripts: use explicit relative imports of contributor_data...
Mads Kiilerich -
r8041:2786730e default
parent child Browse files
Show More
@@ -1,36 +1,36 b''
1 1 #!/usr/bin/env python2
2 2 # -*- coding: utf-8 -*-
3 3
4 4 """
5 5 Kallithea script for generating a quick overview of contributors and their
6 6 commit counts in a given revision set.
7 7 """
8 8 import argparse
9 9 import os
10 10 from collections import Counter
11 11
12 import contributor_data
12 from . import contributor_data
13 13
14 14
15 15 def main():
16 16
17 17 parser = argparse.ArgumentParser(description='Generate a list of committers and commit counts.')
18 18 parser.add_argument('revset',
19 19 help='revision set specifying the commits to count')
20 20 args = parser.parse_args()
21 21
22 22 repo_entries = [
23 23 (contributor_data.name_fixes.get(name) or contributor_data.name_fixes.get(name.rsplit('<', 1)[0].strip()) or name).rsplit('<', 1)[0].strip()
24 24 for name in (line.strip()
25 25 for line in os.popen("""hg log -r '%s' -T '{author}\n'""" % args.revset).readlines())
26 26 ]
27 27
28 28 counter = Counter(repo_entries)
29 29 for name, count in counter.most_common():
30 30 if name == '':
31 31 continue
32 32 print('%4s %s' % (count, name))
33 33
34 34
35 35 if __name__ == '__main__':
36 36 main()
@@ -1,179 +1,179 b''
1 1 #!/usr/bin/env python2
2 2 # -*- coding: utf-8 -*-
3 3
4 4 """
5 5 Kallithea script for maintaining contributor lists from version control
6 6 history.
7 7
8 8 This script and the data in it is a best effort attempt at reverse engineering
9 9 previous attributions and correlate that with version control history while
10 10 preserving all existing copyright statements and attribution. This script is
11 11 processing and summarizing information found elsewhere - it is not by itself
12 12 making any claims. Comments in the script are an attempt at reverse engineering
13 13 possible explanations - they are not showing any intent or confirming it is
14 14 correct.
15 15
16 16 Three files are generated / modified by this script:
17 17
18 18 kallithea/templates/about.html claims to show copyright holders, and the GPL
19 19 license requires such existing "legal notices" to be preserved. We also try to
20 20 keep it updated with copyright holders, but do not claim it is a correct list.
21 21
22 22 CONTRIBUTORS has the purpose of giving credit where credit is due and list all
23 23 the contributor names in the source.
24 24
25 25 kallithea/templates/base/base.html contains the copyright years in the page
26 26 footer.
27 27
28 28 Both make a best effort of listing all copyright holders, but revision control
29 29 history might be a better and more definitive source.
30 30
31 31 Contributors are sorted "fairly" by copyright year and amount of
32 32 contribution.
33 33
34 34 New contributors are listed, without considering if the contribution contains
35 35 copyrightable work.
36 36
37 37 When the copyright might belong to a different legal entity than the
38 38 contributor, the legal entity is given credit too.
39 39 """
40 40
41 41 import os
42 42 import re
43 43 from collections import defaultdict
44 44
45 import contributor_data
45 from . import contributor_data
46 46
47 47
48 48 def sortkey(x):
49 49 """Return key for sorting contributors "fairly":
50 50 * latest contribution
51 51 * first contribution
52 52 * number of contribution years
53 53 * name (with some unicode normalization)
54 54 The entries must be 2-tuples of a list of string years and the unicode name"""
55 55 return (x[0] and -int(x[0][-1]),
56 56 x[0] and int(x[0][0]),
57 57 -len(x[0]),
58 58 x[1].decode('utf-8').lower().replace(u'\xe9', u'e').replace(u'\u0142', u'l')
59 59 )
60 60
61 61
62 62 def nice_years(l, dash='-', join=' '):
63 63 """Convert a list of years into brief range like '1900-1901, 1921'."""
64 64 if not l:
65 65 return ''
66 66 start = end = int(l[0])
67 67 ranges = []
68 68 for year in l[1:] + [0]:
69 69 year = int(year)
70 70 if year == end + 1:
71 71 end = year
72 72 continue
73 73 if start == end:
74 74 ranges.append('%s' % start)
75 75 else:
76 76 ranges.append('%s%s%s' % (start, dash, end))
77 77 start = end = year
78 78 assert start == 0 and end == 0, (start, end)
79 79 return join.join(ranges)
80 80
81 81
82 82 def insert_entries(
83 83 filename,
84 84 all_entries,
85 85 no_entries,
86 86 domain_extra,
87 87 split_re,
88 88 normalize_name,
89 89 format_f):
90 90 """Update file with contributor information.
91 91 all_entries: list of tuples with year and name
92 92 no_entries: set of names or name and year tuples to ignore
93 93 domain_extra: map domain name to extra credit name
94 94 split_re: regexp matching the part of file to rewrite
95 95 normalize_name: function to normalize names for grouping and display
96 96 format_f: function formatting year list and name to a string
97 97 """
98 98 name_years = defaultdict(set)
99 99
100 100 for year, name in all_entries:
101 101 if name in no_entries or (name, year) in no_entries:
102 102 continue
103 103 parts = name.split(' <', 1)
104 104 if len(parts) == 2:
105 105 name = parts[0] + ' <' + parts[1].lower()
106 106 domain = name.split('@', 1)[-1].rstrip('>')
107 107 if domain in domain_extra:
108 108 name_years[domain_extra[domain]].add(year)
109 109 name_years[normalize_name(name)].add(year)
110 110
111 111 l = [(list(sorted(year for year in years if year)), name)
112 112 for name, years in name_years.items()]
113 113 l.sort(key=sortkey)
114 114
115 115 with open(filename) as f:
116 116 pre, post = re.split(split_re, f.read())
117 117
118 118 with open(filename, 'w') as f:
119 119 f.write(pre +
120 120 ''.join(format_f(years, name) for years, name in l) +
121 121 post)
122 122
123 123
124 124 def main():
125 125 repo_entries = [
126 126 (year, contributor_data.name_fixes.get(name) or contributor_data.name_fixes.get(name.rsplit('<', 1)[0].strip()) or name)
127 127 for year, name in
128 128 (line.strip().split(' ', 1)
129 129 for line in os.popen("""hg log -r '::.' -T '{date(date,"%Y")} {author}\n'""").readlines())
130 130 ]
131 131
132 132 insert_entries(
133 133 filename='kallithea/templates/about.html',
134 134 all_entries=repo_entries + contributor_data.other_about + contributor_data.other,
135 135 no_entries=contributor_data.no_about,
136 136 domain_extra=contributor_data.domain_extra,
137 137 split_re=r'(?: <li>Copyright &copy; [^\n]*</li>\n)*',
138 138 normalize_name=lambda name: name.split('<', 1)[0].strip(),
139 139 format_f=lambda years, name: ' <li>Copyright &copy; %s, %s</li>\n' % (nice_years(years, '&ndash;', ', '), name),
140 140 )
141 141
142 142 insert_entries(
143 143 filename='CONTRIBUTORS',
144 144 all_entries=repo_entries + contributor_data.other_contributors + contributor_data.other,
145 145 no_entries=contributor_data.total_ignore,
146 146 domain_extra=contributor_data.domain_extra,
147 147 split_re=r'(?: [^\n]*\n)*',
148 148 normalize_name=lambda name: name,
149 149 format_f=lambda years, name: (' %s%s%s\n' % (name, ' ' if years else '', nice_years(years))),
150 150 )
151 151
152 152 insert_entries(
153 153 filename='kallithea/templates/base/base.html',
154 154 all_entries=repo_entries,
155 155 no_entries=contributor_data.total_ignore,
156 156 domain_extra={},
157 157 split_re=r'(?<=&copy;) .* (?=by various authors)',
158 158 normalize_name=lambda name: '',
159 159 format_f=lambda years, name: ' ' + nice_years(years, '&ndash;', ', ') + ' ',
160 160 )
161 161
162 162 #docs/conf.py:copyright = u'2010-2016 by various authors, licensed as GPLv3.'
163 163 insert_entries(
164 164 filename='docs/conf.py',
165 165 all_entries=repo_entries,
166 166 no_entries=contributor_data.total_ignore,
167 167 domain_extra={},
168 168 split_re=r"(?<=copyright = u').*(?= by various authors)",
169 169 normalize_name=lambda name: '',
170 170 format_f=lambda years, name: nice_years(years, '-', ', '),
171 171 )
172 172
173 173
174 174 if __name__ == '__main__':
175 175 main()
176 176
177 177
178 178 # To list new contributors since last tagging:
179 179 # { hg log -r '::tagged()' -T ' {author}\n {author}\n'; hg log -r '::.' -T ' {author}\n' | sort | uniq; } | sort | uniq -u
General Comments 0
You need to be logged in to leave comments. Login now