##// END OF EJS Templates
make-release: import version and copyright updates from default branch (dba4e770d4b6)...
Thomas De Schampheleire -
r7136:d06c0566 stable
parent child Browse files
Show More
@@ -1,63 +1,71 b''
1 1 #!/bin/bash
2 2 set -e
3 3 set -x
4 4
5 echo "Checking tools needed for uploading stuff"
6 pip freeze | grep '^Sphinx==' || pip install Sphinx
7 pip freeze | grep '^Sphinx-PyPI-upload==' || pip install Sphinx-PyPI-upload
5 echo "Install/verify tools needed for building and uploading stuff"
6 pip install --upgrade -e .
7 pip install --upgrade Sphinx Sphinx-PyPI-upload
8
9 echo "Cleanup and update copyrights ... and clean checkout"
10 scripts/whitespacecleanup.sh
11 scripts/update-copyrights.py
12 hg up -cr .
8 13
9 echo "Verifying everything can build"
10 hg purge --all dist
11 python2 setup.py build_sphinx
12 python2 setup.py compile_catalog # TODO: check for errors
14 echo "Make release build from clean checkout in build/"
15 rm -rf build dist
16 hg archive build
17 cd build
18
19 echo "Check MANIFEST.in"
20 sed -e 's/[^ ]*[ ]*\([^ ]*\).*/\1/g' MANIFEST.in | grep -v '^node_modules/bootstrap\|^kallithea/public/css/style.css' | xargs ls -lad
21
22 echo "Build dist"
23 python2 setup.py compile_catalog
13 24 python2 setup.py sdist
14 25
15 echo "Verifying VERSION from kallithea/__init__.py"
26 echo "Verify VERSION from kallithea/__init__.py"
16 27 namerel=$(cd dist && echo Kallithea-*.tar.gz)
17 28 namerel=${namerel%.tar.gz}
18 29 version=${namerel#Kallithea-}
30 ls -l $(pwd)/dist/$namerel.tar.gz
19 31 echo "Releasing Kallithea $version in directory $namerel"
20 echo "Verifying current revision is tagged for $version"
21 hg log -r "'$version'&." | grep .
22 32
23 echo "Cleaning before making release build"
24 hg up -c .
25 hg revert -a -r null
26 hg up -C "'$version'&."
27 hg purge --all
33 echo "Verify dist file content"
34 ! tar tf dist/Kallithea-$version.tar.gz | grep "$namerel/node_modules/bootstrap/\$"
35
36 echo "Verify docs build"
37 python2 setup.py build_sphinx # not used yet ... but we want to make sure it builds
38
39 cat - << EOT
28 40
29 echo "Building dist file"
30 python2 setup.py compile_catalog
31 python2 setup.py sdist
41 Now, make sure
42 * the copyright and contributor lists have been updated
43 * all tests are passing
44 * release note is ready
45 * announcement is ready
46 * source has been pushed to https://kallithea-scm.org/repos/kallithea
32 47
33 echo "Verifying dist file content"
34 tar tf dist/Kallithea-*.tar.gz | sed "s|^$namerel/||" | LANG=C sort > scripts/manifest
35 hg diff
36 hg up -c . # fail if manifest changed
48 EOT
37 49
38 echo "Now, make sure"
39 echo "* the copyright and contributor lists have been updated"
40 echo "* all tests are passing"
41 echo "* release note is ready"
42 echo "* announcement is ready"
43 echo "* source has been pushed to https://kallithea-scm.org/repos/kallithea"
44 echo
50 echo "Verify current revision is tagged for $version"
51 hg log -r "'$version'&." | grep .
45 52
46 53 echo -n "Enter \"pypi\" to upload Kallithea $version to pypi: "
47 54 read answer
48 55 [ "$answer" = "pypi" ]
49 extraargs=${EMAIL:+--identity=$EMAIL}
50 python2 setup.py sdist upload --sign $extraargs
51 xdg-open https://pypi.python.org/pypi/Kallithea
52 56
53 echo "Uploading docs to pypi"
57 echo "Upload docs to pypi"
54 58 # See https://wiki.python.org/moin/PyPiDocumentationHosting
55 59 python2 setup.py build_sphinx upload_sphinx
56 60 xdg-open https://pythonhosted.org/Kallithea/
57 61 xdg-open http://packages.python.org/Kallithea/installation.html
58 62
59 echo "Rebuilding readthedocs for docs.kallithea-scm.org"
63 echo "Rebuild readthedocs for docs.kallithea-scm.org"
60 64 xdg-open https://readthedocs.org/projects/kallithea/
61 65 curl -X POST http://readthedocs.org/build/kallithea
62 66 xdg-open https://readthedocs.org/builds/kallithea/
63 67 xdg-open http://docs.kallithea-scm.org/en/latest/ # or whatever the branch is
68
69 extraargs=${EMAIL:+--identity=$EMAIL}
70 python2 setup.py sdist upload --sign $extraargs
71 xdg-open https://pypi.python.org/pypi/Kallithea
@@ -1,253 +1,253 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
42 42 # Some committers are so wrong that it doesn't point at any contributor:
43 43 total_ignore = set()
44 44 total_ignore.add('*** failed to import extension hggit: No module named hggit')
45 45 total_ignore.add('<>')
46 46
47 47 # Normalize some committer names where people have contributed under different
48 48 # names or email addresses:
49 49 name_fixes = {}
50 50 name_fixes['Andrew Shadura'] = "Andrew Shadura <andrew@shadura.me>"
51 51 name_fixes['aparkar'] = "Aparkar <aparkar@icloud.com>"
52 52 name_fixes['Aras Pranckevicius'] = "Aras Pranckevičius <aras@unity3d.com>"
53 53 name_fixes['Augosto Hermann'] = "Augusto Herrmann <augusto.herrmann@planejamento.gov.br>"
54 54 name_fixes['"Bradley M. Kuhn" <bkuhn@ebb.org>'] = "Bradley M. Kuhn <bkuhn@sfconservancy.org>"
55 55 name_fixes['dmitri.kuznetsov'] = "Dmitri Kuznetsov"
56 56 name_fixes['Dmitri Kuznetsov'] = "Dmitri Kuznetsov"
57 57 name_fixes['domruf'] = "Dominik Ruf <dominikruf@gmail.com>"
58 58 name_fixes['Ingo von borstel'] = "Ingo von Borstel <kallithea@planetmaker.de>"
59 59 name_fixes['Jan Heylen'] = "Jan Heylen <heyleke@gmail.com>"
60 60 name_fixes['Jason F. Harris'] = "Jason Harris <jason@jasonfharris.com>"
61 61 name_fixes['Jelmer Vernooij'] = "Jelmer VernooΔ³ <jelmer@samba.org>"
62 62 name_fixes['jfh <jason@jasonfharris.com>'] = "Jason Harris <jason@jasonfharris.com>"
63 63 name_fixes['Leonardo Carneiro<leonardo@unity3d.com>'] = "Leonardo Carneiro <leonardo@unity3d.com>"
64 64 name_fixes['leonardo'] = "Leonardo Carneiro <leonardo@unity3d.com>"
65 65 name_fixes['Leonardo <leo@unity3d.com>'] = "Leonardo Carneiro <leonardo@unity3d.com>"
66 66 name_fixes['Les Peabody'] = "Les Peabody <lpeabody@gmail.com>"
67 67 name_fixes['"Lorenzo M. Catucci" <lorenzo@sancho.ccd.uniroma2.it>'] = "Lorenzo M. Catucci <lorenzo@sancho.ccd.uniroma2.it>"
68 68 name_fixes['Lukasz Balcerzak'] = "Łukasz Balcerzak <lukaszbalcerzak@gmail.com>"
69 69 name_fixes['mao <mao@lins.fju.edu.tw>'] = "Ching-Chen Mao <mao@lins.fju.edu.tw>"
70 70 name_fixes['marcink'] = "Marcin KuΕΊmiΕ„ski <marcin@python-works.com>"
71 71 name_fixes['Marcin Kuzminski'] = "Marcin KuΕΊmiΕ„ski <marcin@python-works.com>"
72 72 name_fixes['nansenat16@null.tw'] = "nansenat16 <nansenat16@null.tw>"
73 73 name_fixes['Peter Vitt'] = "Peter Vitt <petervitt@web.de>"
74 74 name_fixes['philip.j@hostdime.com'] = "Philip Jameson <philip.j@hostdime.com>"
75 75 name_fixes['SΓΈren LΓΈvborg'] = "SΓΈren LΓΈvborg <sorenl@unity3d.com>"
76 name_fixes['Thomas De Schampheleire'] = "Thomas De Schampheleire <thomas.de.schampheleire@gmail.com>"
76 name_fixes['Thomas De Schampheleire'] = "Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>"
77 77 name_fixes['Weblate'] = "<>"
78 78 name_fixes['xpol'] = "xpol <xpolife@gmail.com>"
79 79
80 80
81 81 # Some committer email address domains that indicate that another entity might
82 82 # hold some copyright too:
83 83 domain_extra = {}
84 84 domain_extra['unity3d.com'] = "Unity Technologies"
85 85 domain_extra['rhodecode.com'] = "RhodeCode GmbH"
86 86
87 87 # Repository history show some old contributions that traditionally hasn't been
88 88 # listed in about.html - preserve that:
89 89 no_about = set(total_ignore)
90 90 # The following contributors were traditionally not listed in about.html and it
91 91 # seems unclear if the copyright is personal or belongs to a company.
92 92 no_about.add(('Thayne Harbaugh <thayne@fusionio.com>', '2011'))
93 93 no_about.add(('Dies Koper <diesk@fast.au.fujitsu.com>', '2012'))
94 94 no_about.add(('Erwin Kroon <e.kroon@smartmetersolutions.nl>', '2012'))
95 95 no_about.add(('Vincent Caron <vcaron@bearstech.com>', '2012'))
96 96 # These contributors' contributions might be too small to be copyrightable:
97 97 no_about.add(('philip.j@hostdime.com', '2012'))
98 98 no_about.add(('Stefan Engel <mail@engel-stefan.de>', '2012'))
99 99 no_about.add(('Ton Plomp <tcplomp@gmail.com>', '2013'))
100 100 # Was reworked and contributed later and shadowed by other contributions:
101 101 no_about.add(('Sean Farley <sean.michael.farley@gmail.com>', '2013'))
102 102
103 103 # Preserve contributors listed in about.html but not appearing in repository
104 104 # history:
105 105 other_about = [
106 106 ("2011", "Aparkar <aparkar@icloud.com>"),
107 107 ("2010", "RhodeCode GmbH"),
108 108 ("2011", "RhodeCode GmbH"),
109 109 ("2012", "RhodeCode GmbH"),
110 110 ("2013", "RhodeCode GmbH"),
111 111 ]
112 112
113 113 # Preserve contributors listed in CONTRIBUTORS but not appearing in repository
114 114 # history:
115 115 other_contributors = [
116 116 ("", "Andrew Kesterson <andrew@aklabs.net>"),
117 117 ("", "cejones"),
118 118 ("", "David A. SjΓΈen <david.sjoen@westcon.no>"),
119 119 ("", "James Rhodes <jrhodes@redpointsoftware.com.au>"),
120 120 ("", "Jonas Oberschweiber <jonas.oberschweiber@d-velop.de>"),
121 121 ("", "larikale"),
122 122 ("", "RhodeCode GmbH"),
123 123 ("", "Sebastian Kreutzberger <sebastian@rhodecode.com>"),
124 124 ("", "Steve Romanow <slestak989@gmail.com>"),
125 125 ("", "SteveCohen"),
126 126 ("", "Thomas <thomas@rhodecode.com>"),
127 127 ("", "Thomas Waldmann <tw-public@gmx.de>"),
128 128 ]
129 129
130 130
131 131 import os
132 132 import re
133 133 from collections import defaultdict
134 134
135 135
136 136 def sortkey(x):
137 137 """Return key for sorting contributors "fairly":
138 138 * latest contribution
139 139 * first contribution
140 140 * number of contribution years
141 141 * name (with some unicode normalization)
142 142 The entries must be 2-tuples of a list of string years and the unicode name"""
143 143 return (x[0] and -int(x[0][-1]),
144 144 x[0] and int(x[0][0]),
145 145 -len(x[0]),
146 146 x[1].decode('utf8').lower().replace(u'\xe9', u'e').replace(u'\u0142', u'l')
147 147 )
148 148
149 149
150 150 def nice_years(l, dash='-', join=' '):
151 151 """Convert a list of years into brief range like '1900-1901, 1921'."""
152 152 if not l:
153 153 return ''
154 154 start = end = int(l[0])
155 155 ranges = []
156 156 for year in l[1:] + [0]:
157 157 year = int(year)
158 158 if year == end + 1:
159 159 end = year
160 160 continue
161 161 if start == end:
162 162 ranges.append('%s' % start)
163 163 else:
164 164 ranges.append('%s%s%s' % (start, dash, end))
165 165 start = end = year
166 166 assert start == 0 and end == 0, (start, end)
167 167 return join.join(ranges)
168 168
169 169
170 170 def insert_entries(
171 171 filename,
172 172 all_entries,
173 173 no_entries,
174 174 domain_extra,
175 175 split_re,
176 176 normalize_name,
177 177 format_f):
178 178 """Update file with contributor information.
179 179 all_entries: list of tuples with year and name
180 180 no_entries: set of names or name and year tuples to ignore
181 181 domain_extra: map domain name to extra credit name
182 182 split_re: regexp matching the part of file to rewrite
183 183 normalize_name: function to normalize names for grouping and display
184 184 format_f: function formatting year list and name to a string
185 185 """
186 186 name_years = defaultdict(set)
187 187
188 188 for year, name in all_entries:
189 189 if name in no_entries or (name, year) in no_entries:
190 190 continue
191 191 domain = name.split('@', 1)[-1].rstrip('>')
192 192 if domain in domain_extra:
193 193 name_years[domain_extra[domain]].add(year)
194 194 name_years[normalize_name(name)].add(year)
195 195
196 196 l = [(list(sorted(year for year in years if year)), name)
197 197 for name, years in name_years.items()]
198 198 l.sort(key=sortkey)
199 199
200 200 with file(filename) as f:
201 201 pre, post = re.split(split_re, f.read())
202 202
203 203 with file(filename, 'w') as f:
204 204 f.write(pre +
205 205 ''.join(format_f(years, name) for years, name in l) +
206 206 post)
207 207
208 208
209 209 def main():
210 210 repo_entries = [
211 211 (year, name_fixes.get(name) or name_fixes.get(name.rsplit('<', 1)[0].strip()) or name)
212 212 for year, name in
213 213 (line.strip().split(' ', 1)
214 214 for line in os.popen("""hg log -r '::.' -T '{date(date,"%Y")} {author}\n'""").readlines())
215 215 ]
216 216
217 217 insert_entries(
218 218 filename='kallithea/templates/about.html',
219 219 all_entries=repo_entries + other_about,
220 220 no_entries=no_about,
221 221 domain_extra=domain_extra,
222 222 split_re=r'(?: <li>Copyright &copy; [^\n]*</li>\n)*',
223 223 normalize_name=lambda name: name.split('<', 1)[0].strip(),
224 224 format_f=lambda years, name: ' <li>Copyright &copy; %s, %s</li>\n' % (nice_years(years, '&ndash;', ', '), name),
225 225 )
226 226
227 227 insert_entries(
228 228 filename='CONTRIBUTORS',
229 229 all_entries=repo_entries + other_contributors,
230 230 no_entries=total_ignore,
231 231 domain_extra=domain_extra,
232 232 split_re=r'(?: [^\n]*\n)*',
233 233 normalize_name=lambda name: name,
234 234 format_f=lambda years, name: (' %s%s%s\n' % (name, ' ' if years else '', nice_years(years))),
235 235 )
236 236
237 237 insert_entries(
238 238 filename='kallithea/templates/base/base.html',
239 239 all_entries=repo_entries,
240 240 no_entries=total_ignore,
241 241 domain_extra={},
242 242 split_re=r'(?<=&copy;) .* (?=by various authors)',
243 243 normalize_name=lambda name: '',
244 244 format_f=lambda years, name: ' ' + nice_years(years, '&ndash;', ', ') + ' ',
245 245 )
246 246
247 247
248 248 if __name__ == '__main__':
249 249 main()
250 250
251 251
252 252 # To list new contributors since last tagging:
253 253 # { 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