# HG changeset patch # User Mads Kiilerich # Date 2017-07-27 03:02:37 # Node ID a48802bf7134e5270f48eb05e10ccd375366cba9 # Parent 84d8cff41282ae16ab0b935a635182a512ff87a8 # Parent 9b9258f5e2b235d05967c93fe890dd1910774a3e Merge stable diff --git a/.hgsigs b/.hgsigs --- a/.hgsigs +++ b/.hgsigs @@ -1,3 +1,4 @@ 9b3e9e242f5c97cc0c7657e5ac93dce7de61ca16 0 iQEcBAABAgAGBQJWDuAdAAoJEJ1bI/kYT6UUAlYH/ReCa7Im5tvy+ot5oAc7xey/O2rCVHp2h6i82tTWK/0i9EaS4DP+eTbAjV4WJA4qWF5DPenEJ3X9JhrTLNvGkR0f7lUqiFVMTJ472YlSsvIWg38gVFruzwk1cODRfq72o8ERYcRSfzrL4cDpIqjEd/vVVCV/gKVvPmzr4/FED/ZmS0X6T9gxWJo/eWSuLNAxHHtE/pCWDO3XEe+iOm+hHjkyz4Hn2r9/+ucrirnzycH6DnYO/kWvQzBnzgMjJm+1rLZ5cfU89V8zfhv6z0pd8CHZfpKGc2Z8EwVJq9LR+M4/76uDlYXx7IfZAxhRNqN6MC+yvPmDo3382dNr7Wkopi0= 9bf8eb837e785b6856ccfac264e977ce3ebe1535 0 iQEcBAABAgAGBQJW5XaVAAoJEJ1bI/kYT6UUbeMH/AsGg21jTc0tTT+228T+WfrfkbxrPkkULQF/Eo3ChlrhnFZ5B1y7ellSx6XGas7yKpqHHtNmrVwY3KBfUaYEljML/osEt1kvM6JGcd0vDbAW1uA2sdJR2AXmf32MjguFVhmYi9Lj79WYtgg241YGPe4dH0ompNFVqazNxCfmDBZijzSkF57FURMpV2e6+MyNq0txSo9Q82eALy0GAIX7NKQcxtynxG9ETzVzuVpeNE9MEZh0ObbUtPGezd55GXXcVqI8ZEurZwf6KHnd5M+5wxIZf84gM/k4QgQbRiIxNj4QfVmTZlVNSkC7PwSbF8twZPjlAprwldYvMi/c7ZVocEY= a84d40e9481fcea4dafadee86b03f0dd401527d6 0 iQEcBAABAgAGBQJXJ4XhAAoJEJ1bI/kYT6UUKaIH/i33ZiT95pWF3pHEftgrZWvMwvz9tAuoHgf7ntkIUPnxfNteXKw8FiKcSQ9f8I41VyML+rqsnBBIfltJknfoqTV+9jNkHwc62OfcqQ3RbBDXQbcSi1CHn2ihJiZadqiKEyUw7JJqOMyWp+AWQyywcF/ea+pwXPJG5A2fd4vnBWHSxhD+6Ig1KipZNORzZY7fAec185M7NOZCZC+5qOLIkoQZaGq+D2Aipx5eZkpgFd4W+0LQY1ywMV5CiOY1OG0mry7l6NfIZvPY9Kiwg37G6ZUi8fhwVvn6Y8UACcAnWunBfKt9PWK0rAgNyJ9HDk/+3S5g6HcNKUb6YRTzEcLshIc= +64ea7ea0923618a0c117acebb816a6f0d162bfdb 0 iQEvBAABCAAZBQJZeN4NEhxhbmRyZXdAc2hhZHVyYS5tZQAKCRCdWyP5GE+lFGi/CACBEWfdtZNumWz5LJ6yHbiceEDXZ+9aD44EU3J3VfbRwLeZhQ7J0WwBCFg0qPxh08O+TMaeRP4ur20hczyR6u8fwmIc9KDmNZHujlG0Q6GkNSMizyfJgf/MYJD+03q2Z0S4e9QdPfc746TBZKaqqauV0uVjtd7+m3L4R+Qh5shxBNxshqGGWtMtXpO9iojCJEqxde9RVm+w9NidKdCLGoDlVpJ42iFSrUMeWBnVUMRhOiz6XKUrIPEjUfWMFe0gOR55wZcF3tJo8XBqqqhecI69cmLmkv1xG92V+jC5gTC3STYTASJqXHKEp2cRvUGbHrFF9ODBvcYjj+VsY5r2aU1l diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -64,3 +64,4 @@ c6e32714336345403adf76abb6ebf9b8116fcdc7 9b3e9e242f5c97cc0c7657e5ac93dce7de61ca16 0.3 9bf8eb837e785b6856ccfac264e977ce3ebe1535 0.3.1 a84d40e9481fcea4dafadee86b03f0dd401527d6 0.3.2 +64ea7ea0923618a0c117acebb816a6f0d162bfdb 0.3.3 diff --git a/CONTRIBUTORS b/CONTRIBUTORS --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1,18 +1,30 @@ List of contributors to Kallithea project: - Mads Kiilerich 2012-2016 + Mads Kiilerich 2012-2017 + Unity Technologies 2012-2017 + Andrew Shadura 2012 2014-2017 + Dominik Ruf 2012 2014-2017 + Thomas De Schampheleire 2014-2017 + Søren Løvborg 2015-2017 + Sam Jaques 2015 2017 + Asterios Dimitriou 2016-2017 + Mads Kiilerich 2016-2017 + Alessandro Molina 2017 + Anton Schur 2017 + Ching-Chen Mao 2017 + Eivind Tagseth 2017 + FUJIWARA Katsunori 2017 + Karl Goetz 2017 + Marko Semet 2017 + Viktar Vauchkevich 2017 Takumi IINO 2012-2016 - Unity Technologies 2012-2016 - Andrew Shadura 2012 2014-2016 - Dominik Ruf 2012 2014-2016 - Thomas De Schampheleire 2014-2016 Étienne Gilli 2015-2016 Jan Heylen 2015-2016 Robert Martinez 2015-2016 Robert Rauch 2015-2016 - Søren Løvborg 2015-2016 Angel Ezquerra 2016 - Asterios Dimitriou 2016 + Anton Shestakov 2016 + Brandon Jones 2016 Kateryna Musina 2016 Konstantin Veretennicov 2016 Oscar Curero 2016 @@ -49,7 +61,6 @@ List of contributors to Kallithea projec Niemand Jedermann 2015 Peter Vitt 2015 Ronny Pfannschmidt 2015 - Sam Jaques 2015 Tuux 2015 Viktar Palstsiuk 2015 Ante Ilic 2014 diff --git a/kallithea/templates/about.html b/kallithea/templates/about.html --- a/kallithea/templates/about.html +++ b/kallithea/templates/about.html @@ -27,19 +27,30 @@ necessarily limited to the following:

    -
  • Copyright © 2012–2016, Mads Kiilerich
  • +
  • Copyright © 2012–2017, Mads Kiilerich
  • +
  • Copyright © 2012–2017, Unity Technologies
  • +
  • Copyright © 2012, 2014–2017, Andrew Shadura
  • +
  • Copyright © 2012, 2014–2017, Dominik Ruf
  • +
  • Copyright © 2014–2017, Thomas De Schampheleire
  • +
  • Copyright © 2015–2017, Søren Løvborg
  • +
  • Copyright © 2015, 2017, Sam Jaques
  • +
  • Copyright © 2016–2017, Asterios Dimitriou
  • +
  • Copyright © 2017, Alessandro Molina
  • +
  • Copyright © 2017, Anton Schur
  • +
  • Copyright © 2017, Ching-Chen Mao
  • +
  • Copyright © 2017, Eivind Tagseth
  • +
  • Copyright © 2017, FUJIWARA Katsunori
  • +
  • Copyright © 2017, Karl Goetz
  • +
  • Copyright © 2017, Marko Semet
  • +
  • Copyright © 2017, Viktar Vauchkevich
  • Copyright © 2012–2016, Takumi IINO
  • -
  • Copyright © 2012–2016, Unity Technologies
  • -
  • Copyright © 2012, 2014–2016, Andrew Shadura
  • -
  • Copyright © 2012, 2014–2016, Dominik Ruf
  • -
  • Copyright © 2014–2016, Thomas De Schampheleire
  • Copyright © 2015–2016, Étienne Gilli
  • Copyright © 2015–2016, Jan Heylen
  • Copyright © 2015–2016, Robert Martinez
  • Copyright © 2015–2016, Robert Rauch
  • -
  • Copyright © 2015–2016, Søren Løvborg
  • Copyright © 2016, Angel Ezquerra
  • -
  • Copyright © 2016, Asterios Dimitriou
  • +
  • Copyright © 2016, Anton Shestakov
  • +
  • Copyright © 2016, Brandon Jones
  • Copyright © 2016, Kateryna Musina
  • Copyright © 2016, Konstantin Veretennicov
  • Copyright © 2016, Oscar Curero
  • @@ -76,7 +87,6 @@
  • Copyright © 2015, Niemand Jedermann
  • Copyright © 2015, Peter Vitt
  • Copyright © 2015, Ronny Pfannschmidt
  • -
  • Copyright © 2015, Sam Jaques
  • Copyright © 2015, Tuux
  • Copyright © 2015, Viktar Palstsiuk
  • Copyright © 2014, Ante Ilic
  • diff --git a/scripts/update-copyrights.py b/scripts/update-copyrights.py new file mode 100755 --- /dev/null +++ b/scripts/update-copyrights.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +""" +Kallithea script for maintaining contributor lists from version control +history. + +This script and the data in it is a best effort attempt at reverse engineering +previous attributions and correlate that with version control history while +preserving all existing copyright statements and attribution. This script is +processing and summarizing information found elsewhere - it is not by itself +making any claims. Comments in the script are an attempt at reverse engineering +possible explanations - they are not showing any intent or confirming it is +correct. + +Three files are generated / modified by this script: + +kallithea/templates/about.html claims to show copyright holders, and the GPL +license requires such existing "legal notices" to be preserved. We also try to +keep it updated with copyright holders, but do not claim it is a correct list. + +CONTRIBUTORS has the purpose of giving credit where credit is due and list all +the contributor names in the source. + +kallithea/templates/base/base.html contains the copyright years in the page +footer. + +Both make a best effort of listing all copyright holders, but revision control +history might be a better and more definitive source. + +Contributors are sorted "fairly" by copyright year and amount of +contribution. + +New contributors are listed, without considering if the contribution contains +copyrightable work. + +When the copyright might belong to a different legal entity than the +contributor, the legal entity is given credit too. +""" + + +# Some committers are so wrong that it doesn't point at any contributor: +total_ignore = set() +total_ignore.add('*** failed to import extension hggit: No module named hggit') +total_ignore.add('<>') + +# Normalize some committer names where people have contributed under different +# names or email addresses: +name_fixes = {} +name_fixes['Andrew Shadura'] = "Andrew Shadura " +name_fixes['aparkar'] = "Aparkar " +name_fixes['Aras Pranckevicius'] = "Aras Pranckevičius " +name_fixes['Augosto Hermann'] = "Augusto Herrmann " +name_fixes['"Bradley M. Kuhn" '] = "Bradley M. Kuhn " +name_fixes['dmitri.kuznetsov'] = "Dmitri Kuznetsov" +name_fixes['Dmitri Kuznetsov'] = "Dmitri Kuznetsov" +name_fixes['domruf'] = "Dominik Ruf " +name_fixes['Ingo von borstel'] = "Ingo von Borstel " +name_fixes['Jan Heylen'] = "Jan Heylen " +name_fixes['Jason F. Harris'] = "Jason Harris " +name_fixes['Jelmer Vernooij'] = "Jelmer Vernooij " +name_fixes['jfh '] = "Jason Harris " +name_fixes['Leonardo Carneiro'] = "Leonardo Carneiro " +name_fixes['leonardo'] = "Leonardo Carneiro " +name_fixes['Leonardo '] = "Leonardo Carneiro " +name_fixes['Les Peabody'] = "Les Peabody " +name_fixes['"Lorenzo M. Catucci" '] = "Lorenzo M. Catucci " +name_fixes['Lukasz Balcerzak'] = "Łukasz Balcerzak " +name_fixes['mao '] = "Ching-Chen Mao " +name_fixes['marcink'] = "Marcin Kuźmiński " +name_fixes['Marcin Kuzminski'] = "Marcin Kuźmiński " +name_fixes['nansenat16@null.tw'] = "nansenat16 " +name_fixes['Peter Vitt'] = "Peter Vitt " +name_fixes['philip.j@hostdime.com'] = "Philip Jameson " +name_fixes['Søren Løvborg'] = "Søren Løvborg " +name_fixes['Thomas De Schampheleire'] = "Thomas De Schampheleire " +name_fixes['Weblate'] = "<>" +name_fixes['xpol'] = "xpol " + + +# Some committer email address domains that indicate that another entity might +# hold some copyright too: +domain_extra = {} +domain_extra['unity3d.com'] = "Unity Technologies" +domain_extra['rhodecode.com'] = "RhodeCode GmbH" + +# Repository history show some old contributions that traditionally hasn't been +# listed in about.html - preserve that: +no_about = set(total_ignore) +# The following contributors were traditionally not listed in about.html and it +# seems unclear if the copyright is personal or belongs to a company. +no_about.add(('Thayne Harbaugh ', '2011')) +no_about.add(('Dies Koper ', '2012')) +no_about.add(('Erwin Kroon ', '2012')) +no_about.add(('Vincent Caron ', '2012')) +# These contributors' contributions might be too small to be copyrightable: +no_about.add(('philip.j@hostdime.com', '2012')) +no_about.add(('Stefan Engel ', '2012')) +no_about.add(('Ton Plomp ', '2013')) +# Was reworked and contributed later and shadowed by other contributions: +no_about.add(('Sean Farley ', '2013')) + +# Preserve contributors listed in about.html but not appearing in repository +# history: +other_about = [ + ("2011", "Aparkar "), + ("2010", "RhodeCode GmbH"), + ("2011", "RhodeCode GmbH"), + ("2012", "RhodeCode GmbH"), + ("2013", "RhodeCode GmbH"), +] + +# Preserve contributors listed in CONTRIBUTORS but not appearing in repository +# history: +other_contributors = [ + ("", "Andrew Kesterson "), + ("", "cejones"), + ("", "David A. Sjøen "), + ("", "James Rhodes "), + ("", "Jonas Oberschweiber "), + ("", "larikale"), + ("", "RhodeCode GmbH"), + ("", "Sebastian Kreutzberger "), + ("", "Steve Romanow "), + ("", "SteveCohen"), + ("", "Thomas "), + ("", "Thomas Waldmann "), +] + + +import os +import re +from collections import defaultdict + + +def sortkey(x): + """Return key for sorting contributors "fairly": + * latest contribution + * first contribution + * number of contribution years + * name (with some unicode normalization) + The entries must be 2-tuples of a list of string years and the unicode name""" + return (x[0] and -int(x[0][-1]), + x[0] and int(x[0][0]), + -len(x[0]), + x[1].decode('utf8').lower().replace(u'\xe9', u'e').replace(u'\u0142', u'l') + ) + + +def nice_years(l, dash='-', join=' '): + """Convert a list of years into brief range like '1900-1901, 1921'.""" + if not l: + return '' + start = end = int(l[0]) + ranges = [] + for year in l[1:] + [0]: + year = int(year) + if year == end + 1: + end = year + continue + if start == end: + ranges.append('%s' % start) + else: + ranges.append('%s%s%s' % (start, dash, end)) + start = end = year + assert start == 0 and end == 0, (start, end) + return join.join(ranges) + + +def insert_entries( + filename, + all_entries, + no_entries, + domain_extra, + split_re, + normalize_name, + format_f): + """Update file with contributor information. + all_entries: list of tuples with year and name + no_entries: set of names or name and year tuples to ignore + domain_extra: map domain name to extra credit name + split_re: regexp matching the part of file to rewrite + normalize_name: function to normalize names for grouping and display + format_f: function formatting year list and name to a string + """ + name_years = defaultdict(set) + + for year, name in all_entries: + if name in no_entries or (name, year) in no_entries: + continue + domain = name.split('@', 1)[-1].rstrip('>') + if domain in domain_extra: + name_years[domain_extra[domain]].add(year) + name_years[normalize_name(name)].add(year) + + l = [(list(sorted(year for year in years if year)), name) + for name, years in name_years.items()] + l.sort(key=sortkey) + + with file(filename) as f: + pre, post = re.split(split_re, f.read()) + + with file(filename, 'w') as f: + f.write(pre + + ''.join(format_f(years, name) for years, name in l) + + post) + + +def main(): + repo_entries = [ + (year, name_fixes.get(name) or name_fixes.get(name.rsplit('<', 1)[0].strip()) or name) + for year, name in + (line.strip().split(' ', 1) + for line in os.popen("""hg log -r '::.' -T '{date(date,"%Y")} {author}\n'""").readlines()) + ] + + insert_entries( + filename='kallithea/templates/about.html', + all_entries=repo_entries + other_about, + no_entries=no_about, + domain_extra=domain_extra, + split_re=r'(?:
  • Copyright © [^\n]*
  • \n)*', + normalize_name=lambda name: name.split('<', 1)[0].strip(), + format_f=lambda years, name: '
  • Copyright © %s, %s
  • \n' % (nice_years(years, '–', ', '), name), + ) + + insert_entries( + filename='CONTRIBUTORS', + all_entries=repo_entries + other_contributors, + no_entries=total_ignore, + domain_extra=domain_extra, + split_re=r'(?: [^\n]*\n)*', + normalize_name=lambda name: name, + format_f=lambda years, name: (' %s%s%s\n' % (name, ' ' if years else '', nice_years(years))), + ) + + insert_entries( + filename='kallithea/templates/base/base.html', + all_entries=repo_entries, + no_entries=total_ignore, + domain_extra={}, + split_re=r'(?<=©) .* (?=by various authors)', + normalize_name=lambda name: '', + format_f=lambda years, name: ' ' + nice_years(years, '–', ', ') + ' ', + ) + + +if __name__ == '__main__': + main() + + +# To list new contributors since last tagging: +# { hg log -r '::tagged()' -T ' {author}\n {author}\n'; hg log -r '::.' -T ' {author}\n' | sort | uniq; } | sort | uniq -u