##// END OF EJS Templates
update-copyrights: fixup double entry for Lars Kruse and regenerate...
Thomas De Schampheleire -
r7475:6b4a1302 default
parent child Browse files
Show More
@@ -1,136 +1,145 b''
1 List of contributors to Kallithea project:
1 List of contributors to Kallithea project:
2
2
3 Andrej Shadura <andrew@shadura.me> 2012 2014-2017 2019
4 Thomas De Schampheleire <thomas.de_schampheleire@nokia.com> 2014-2019
5 Mads Kiilerich <mads@kiilerich.com> 2016-2019
6 Edmund Wong <ewong@crazy-cat.org> 2019
7 Hosted Weblate <hosted@weblate.org> 2019
8 Manuel Jacob <me@manueljacob.de> 2019
3 Dominik Ruf <dominikruf@gmail.com> 2012 2014-2018
9 Dominik Ruf <dominikruf@gmail.com> 2012 2014-2018
4 Thomas De Schampheleire <thomas.de_schampheleire@nokia.com> 2014-2018
10 Michal ČihaΕ™ <michal@cihar.com> 2014-2015 2018
5 Branko Majic <branko@majic.rs> 2015 2018
11 Branko Majic <branko@majic.rs> 2015 2018
6 Mads Kiilerich <mads@kiilerich.com> 2016-2018
12 Allan NordhΓΈy <epost@anotheragency.no> 2017-2018
7 Chris Rule <crule@aegistg.com> 2018
13 Chris Rule <crule@aegistg.com> 2018
14 JesΓΊs SΓ‘nchez <jsanchezfdz95@gmail.com> 2018
8 Patrick Vane <patrick_vane@lowentry.com> 2018
15 Patrick Vane <patrick_vane@lowentry.com> 2018
16 Pheng Heong Tan <phtan90@gmail.com> 2018
17 ssantos <ssantos@web.de> 2018
18 Максим Π―ΠΊΠΈΠΌΡ‡ΡƒΠΊ <xpinovo@gmail.com> 2018
19 ΠœΠ°Ρ€Ρ Π―ΠΌΠ±Π°Ρ€ <mjambarmeta@gmail.com> 2018
9 Mads Kiilerich <madski@unity3d.com> 2012-2017
20 Mads Kiilerich <madski@unity3d.com> 2012-2017
10 Unity Technologies 2012-2017
21 Unity Technologies 2012-2017
11 Andrej Shadura <andrew@shadura.me> 2012 2014-2017
12 Γ‰tienne Gilli <etienne.gilli@gmail.com> 2015-2017
22 Γ‰tienne Gilli <etienne.gilli@gmail.com> 2015-2017
13 SΓΈren LΓΈvborg <sorenl@unity3d.com> 2015-2017
23 SΓΈren LΓΈvborg <sorenl@unity3d.com> 2015-2017
14 Sam Jaques <sam.jaques@me.com> 2015 2017
24 Sam Jaques <sam.jaques@me.com> 2015 2017
15 Asterios Dimitriou <steve@pci.gr> 2016-2017
25 Asterios Dimitriou <steve@pci.gr> 2016-2017
16 Alessandro Molina <alessandro.molina@axant.it> 2017
26 Alessandro Molina <alessandro.molina@axant.it> 2017
17 Anton Schur <tonich.sh@gmail.com> 2017
27 Anton Schur <tonich.sh@gmail.com> 2017
18 Ching-Chen Mao <mao@lins.fju.edu.tw> 2017
28 Ching-Chen Mao <mao@lins.fju.edu.tw> 2017
19 Eivind Tagseth <eivindt@gmail.com> 2017
29 Eivind Tagseth <eivindt@gmail.com> 2017
20 FUJIWARA Katsunori <foozy@lares.dti.ne.jp> 2017
30 FUJIWARA Katsunori <foozy@lares.dti.ne.jp> 2017
21 Holger Schramm <info@schramm.by> 2017
31 Holger Schramm <info@schramm.by> 2017
22 Karl Goetz <karl@kgoetz.id.au> 2017
32 Karl Goetz <karl@kgoetz.id.au> 2017
23 Lars Kruse <devel@sumpfralle.de> 2017
33 Lars Kruse <devel@sumpfralle.de> 2017
24 Marko Semet <markosemet@googlemail.com> 2017
34 Marko Semet <markosemet@googlemail.com> 2017
25 Viktar Vauchkevich <victorenator@gmail.com> 2017
35 Viktar Vauchkevich <victorenator@gmail.com> 2017
26 Takumi IINO <trot.thunder@gmail.com> 2012-2016
36 Takumi IINO <trot.thunder@gmail.com> 2012-2016
27 Jan Heylen <heyleke@gmail.com> 2015-2016
37 Jan Heylen <heyleke@gmail.com> 2015-2016
28 Robert Martinez <ntttq@inboxen.org> 2015-2016
38 Robert Martinez <ntttq@inboxen.org> 2015-2016
29 Robert Rauch <mail@robertrauch.de> 2015-2016
39 Robert Rauch <mail@robertrauch.de> 2015-2016
30 Angel Ezquerra <angel.ezquerra@gmail.com> 2016
40 Angel Ezquerra <angel.ezquerra@gmail.com> 2016
31 Anton Shestakov <av6@dwimlabs.net> 2016
41 Anton Shestakov <av6@dwimlabs.net> 2016
32 Brandon Jones <bjones14@gmail.com> 2016
42 Brandon Jones <bjones14@gmail.com> 2016
33 Kateryna Musina <kateryna@unity3d.com> 2016
43 Kateryna Musina <kateryna@unity3d.com> 2016
34 Konstantin Veretennicov <kveretennicov@gmail.com> 2016
44 Konstantin Veretennicov <kveretennicov@gmail.com> 2016
35 Oscar Curero <oscar@naiandei.net> 2016
45 Oscar Curero <oscar@naiandei.net> 2016
36 Robert James Dennington <tinytimrob@googlemail.com> 2016
46 Robert James Dennington <tinytimrob@googlemail.com> 2016
37 timeless@gmail.com 2016
47 timeless@gmail.com 2016
38 YFdyh000 <yfdyh000@gmail.com> 2016
48 YFdyh000 <yfdyh000@gmail.com> 2016
39 Aras Pranckevičius <aras@unity3d.com> 2012-2013 2015
49 Aras Pranckevičius <aras@unity3d.com> 2012-2013 2015
40 Sean Farley <sean.michael.farley@gmail.com> 2013-2015
50 Sean Farley <sean.michael.farley@gmail.com> 2013-2015
41 Christian Oyarzun <oyarzun@gmail.com> 2014-2015
51 Christian Oyarzun <oyarzun@gmail.com> 2014-2015
42 Joseph Rivera <rivera.d.joseph@gmail.com> 2014-2015
52 Joseph Rivera <rivera.d.joseph@gmail.com> 2014-2015
43 Michal ČihaΕ™ <michal@cihar.com> 2014-2015
44 Anatoly Bubenkov <bubenkoff@gmail.com> 2015
53 Anatoly Bubenkov <bubenkoff@gmail.com> 2015
45 Andrew Bartlett <abartlet@catalyst.net.nz> 2015
54 Andrew Bartlett <abartlet@catalyst.net.nz> 2015
46 BalÑzs Úr <urbalazs@gmail.com> 2015
55 BalÑzs Úr <urbalazs@gmail.com> 2015
47 Ben Finney <ben@benfinney.id.au> 2015
56 Ben Finney <ben@benfinney.id.au> 2015
48 Daniel Hobley <danielh@unity3d.com> 2015
57 Daniel Hobley <danielh@unity3d.com> 2015
49 David Avigni <david.avigni@ankapi.com> 2015
58 David Avigni <david.avigni@ankapi.com> 2015
50 Denis Blanchette <dblanchette@coveo.com> 2015
59 Denis Blanchette <dblanchette@coveo.com> 2015
51 duanhongyi <duanhongyi@doopai.com> 2015
60 duanhongyi <duanhongyi@doopai.com> 2015
52 EriCSN Chang <ericsning@gmail.com> 2015
61 EriCSN Chang <ericsning@gmail.com> 2015
53 Grzegorz Krason <grzegorz.krason@gmail.com> 2015
62 Grzegorz Krason <grzegorz.krason@gmail.com> 2015
54 JiΕ™Γ­ Suchan <yed@vanyli.net> 2015
63 JiΕ™Γ­ Suchan <yed@vanyli.net> 2015
55 Kazunari Kobayashi <kobanari@nifty.com> 2015
64 Kazunari Kobayashi <kobanari@nifty.com> 2015
56 Kevin Bullock <kbullock@ringworld.org> 2015
65 Kevin Bullock <kbullock@ringworld.org> 2015
57 kobanari <kobanari@nifty.com> 2015
66 kobanari <kobanari@nifty.com> 2015
58 Marc Abramowitz <marc@marc-abramowitz.com> 2015
67 Marc Abramowitz <marc@marc-abramowitz.com> 2015
59 Marc Villetard <marc.villetard@gmail.com> 2015
68 Marc Villetard <marc.villetard@gmail.com> 2015
60 Matthias Zilk <matthias.zilk@gmail.com> 2015
69 Matthias Zilk <matthias.zilk@gmail.com> 2015
61 Michael Pohl <michael@mipapo.de> 2015
70 Michael Pohl <michael@mipapo.de> 2015
62 Michael V. DePalatis <mike@depalatis.net> 2015
71 Michael V. DePalatis <mike@depalatis.net> 2015
63 Morten Skaaning <mortens@unity3d.com> 2015
72 Morten Skaaning <mortens@unity3d.com> 2015
64 Nick High <nick@silverchip.org> 2015
73 Nick High <nick@silverchip.org> 2015
65 Niemand Jedermann <predatorix@web.de> 2015
74 Niemand Jedermann <predatorix@web.de> 2015
66 Peter Vitt <petervitt@web.de> 2015
75 Peter Vitt <petervitt@web.de> 2015
67 Ronny Pfannschmidt <opensource@ronnypfannschmidt.de> 2015
76 Ronny Pfannschmidt <opensource@ronnypfannschmidt.de> 2015
68 Tuux <tuxa@galaxie.eu.org> 2015
77 Tuux <tuxa@galaxie.eu.org> 2015
69 Viktar Palstsiuk <vipals@gmail.com> 2015
78 Viktar Palstsiuk <vipals@gmail.com> 2015
70 Ante Ilic <ante@unity3d.com> 2014
79 Ante Ilic <ante@unity3d.com> 2014
71 Bradley M. Kuhn <bkuhn@sfconservancy.org> 2014
80 Bradley M. Kuhn <bkuhn@sfconservancy.org> 2014
72 Calinou <calinou@opmbx.org> 2014
81 Calinou <calinou@opmbx.org> 2014
73 Daniel Anderson <daniel@dattrix.com> 2014
82 Daniel Anderson <daniel@dattrix.com> 2014
74 Henrik Stuart <hg@hstuart.dk> 2014
83 Henrik Stuart <hg@hstuart.dk> 2014
75 Ingo von Borstel <kallithea@planetmaker.de> 2014
84 Ingo von Borstel <kallithea@planetmaker.de> 2014
76 Jelmer VernooΔ³ <jelmer@samba.org> 2014
85 Jelmer VernooΔ³ <jelmer@samba.org> 2014
77 Jim Hague <jim.hague@acm.org> 2014
86 Jim Hague <jim.hague@acm.org> 2014
78 Matt Fellows <kallithea@matt-fellows.me.uk> 2014
87 Matt Fellows <kallithea@matt-fellows.me.uk> 2014
79 Max Roman <max@choloclos.se> 2014
88 Max Roman <max@choloclos.se> 2014
80 Na'Tosha Bard <natosha@unity3d.com> 2014
89 Na'Tosha Bard <natosha@unity3d.com> 2014
81 Rasmus Selsmark <rasmuss@unity3d.com> 2014
90 Rasmus Selsmark <rasmuss@unity3d.com> 2014
82 Tim Freund <tim@freunds.net> 2014
91 Tim Freund <tim@freunds.net> 2014
83 Travis Burtrum <android@moparisthebest.com> 2014
92 Travis Burtrum <android@moparisthebest.com> 2014
84 Zoltan Gyarmati <mr.zoltan.gyarmati@gmail.com> 2014
93 Zoltan Gyarmati <mr.zoltan.gyarmati@gmail.com> 2014
85 Marcin KuΕΊmiΕ„ski <marcin@python-works.com> 2010-2013
94 Marcin KuΕΊmiΕ„ski <marcin@python-works.com> 2010-2013
86 xpol <xpolife@gmail.com> 2012-2013
95 xpol <xpolife@gmail.com> 2012-2013
87 Aparkar <aparkar@icloud.com> 2013
96 Aparkar <aparkar@icloud.com> 2013
88 Dennis Brakhane <brakhane@googlemail.com> 2013
97 Dennis Brakhane <brakhane@googlemail.com> 2013
89 Grzegorz RoΕΌniecki <xaerxess@gmail.com> 2013
98 Grzegorz RoΕΌniecki <xaerxess@gmail.com> 2013
90 Jonathan Sternberg <jonathansternberg@gmail.com> 2013
99 Jonathan Sternberg <jonathansternberg@gmail.com> 2013
91 Leonardo Carneiro <leonardo@unity3d.com> 2013
100 Leonardo Carneiro <leonardo@unity3d.com> 2013
92 Magnus Ericmats <magnus.ericmats@gmail.com> 2013
101 Magnus Ericmats <magnus.ericmats@gmail.com> 2013
93 Martin Vium <martinv@unity3d.com> 2013
102 Martin Vium <martinv@unity3d.com> 2013
94 Simon Lopez <simon.lopez@slopez.org> 2013
103 Simon Lopez <simon.lopez@slopez.org> 2013
95 Ton Plomp <tcplomp@gmail.com> 2013
104 Ton Plomp <tcplomp@gmail.com> 2013
96 Augusto Herrmann <augusto.herrmann@planejamento.gov.br> 2011-2012
105 Augusto Herrmann <augusto.herrmann@planejamento.gov.br> 2011-2012
97 Dan Sheridan <djs@adelard.com> 2012
106 Dan Sheridan <djs@adelard.com> 2012
98 Dies Koper <diesk@fast.au.fujitsu.com> 2012
107 Dies Koper <diesk@fast.au.fujitsu.com> 2012
99 Erwin Kroon <e.kroon@smartmetersolutions.nl> 2012
108 Erwin Kroon <e.kroon@smartmetersolutions.nl> 2012
100 H Waldo G <gwaldo@gmail.com> 2012
109 H Waldo G <gwaldo@gmail.com> 2012
101 hppj <hppj@postmage.biz> 2012
110 hppj <hppj@postmage.biz> 2012
102 Indra Talip <indra.talip@gmail.com> 2012
111 Indra Talip <indra.talip@gmail.com> 2012
103 mikespook 2012
112 mikespook 2012
104 nansenat16 <nansenat16@null.tw> 2012
113 nansenat16 <nansenat16@null.tw> 2012
105 Philip Jameson <philip.j@hostdime.com> 2012
114 Philip Jameson <philip.j@hostdime.com> 2012
106 Raoul Thill <raoul.thill@gmail.com> 2012
115 Raoul Thill <raoul.thill@gmail.com> 2012
107 Stefan Engel <mail@engel-stefan.de> 2012
116 Stefan Engel <mail@engel-stefan.de> 2012
108 Tony Bussieres <t.bussieres@gmail.com> 2012
117 Tony Bussieres <t.bussieres@gmail.com> 2012
109 Vincent Caron <vcaron@bearstech.com> 2012
118 Vincent Caron <vcaron@bearstech.com> 2012
110 Vincent Duvert <vincent@duvert.net> 2012
119 Vincent Duvert <vincent@duvert.net> 2012
111 Vladislav Poluhin <nuklea@gmail.com> 2012
120 Vladislav Poluhin <nuklea@gmail.com> 2012
112 Zachary Auclair <zach101@gmail.com> 2012
121 Zachary Auclair <zach101@gmail.com> 2012
113 Ankit Solanki <ankit.solanki@gmail.com> 2011
122 Ankit Solanki <ankit.solanki@gmail.com> 2011
114 Dmitri Kuznetsov 2011
123 Dmitri Kuznetsov 2011
115 Jared Bunting <jared.bunting@peachjean.com> 2011
124 Jared Bunting <jared.bunting@peachjean.com> 2011
116 Jason Harris <jason@jasonfharris.com> 2011
125 Jason Harris <jason@jasonfharris.com> 2011
117 Les Peabody <lpeabody@gmail.com> 2011
126 Les Peabody <lpeabody@gmail.com> 2011
118 Liad Shani <liadff@gmail.com> 2011
127 Liad Shani <liadff@gmail.com> 2011
119 Lorenzo M. Catucci <lorenzo@sancho.ccd.uniroma2.it> 2011
128 Lorenzo M. Catucci <lorenzo@sancho.ccd.uniroma2.it> 2011
120 Matt Zuba <matt.zuba@goodwillaz.org> 2011
129 Matt Zuba <matt.zuba@goodwillaz.org> 2011
121 Nicolas VINOT <aeris@imirhil.fr> 2011
130 Nicolas VINOT <aeris@imirhil.fr> 2011
122 Shawn K. O'Shea <shawn@eth0.net> 2011
131 Shawn K. O'Shea <shawn@eth0.net> 2011
123 Thayne Harbaugh <thayne@fusionio.com> 2011
132 Thayne Harbaugh <thayne@fusionio.com> 2011
124 Łukasz Balcerzak <lukaszbalcerzak@gmail.com> 2010
133 Łukasz Balcerzak <lukaszbalcerzak@gmail.com> 2010
125 Andrew Kesterson <andrew@aklabs.net>
134 Andrew Kesterson <andrew@aklabs.net>
126 cejones
135 cejones
127 David A. SjΓΈen <david.sjoen@westcon.no>
136 David A. SjΓΈen <david.sjoen@westcon.no>
128 James Rhodes <jrhodes@redpointsoftware.com.au>
137 James Rhodes <jrhodes@redpointsoftware.com.au>
129 Jonas Oberschweiber <jonas.oberschweiber@d-velop.de>
138 Jonas Oberschweiber <jonas.oberschweiber@d-velop.de>
130 larikale
139 larikale
131 RhodeCode GmbH
140 RhodeCode GmbH
132 Sebastian Kreutzberger <sebastian@rhodecode.com>
141 Sebastian Kreutzberger <sebastian@rhodecode.com>
133 Steve Romanow <slestak989@gmail.com>
142 Steve Romanow <slestak989@gmail.com>
134 SteveCohen
143 SteveCohen
135 Thomas <thomas@rhodecode.com>
144 Thomas <thomas@rhodecode.com>
136 Thomas Waldmann <tw-public@gmx.de>
145 Thomas Waldmann <tw-public@gmx.de>
@@ -1,175 +1,184 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3 <%block name="title">
3 <%block name="title">
4 ${_('About')}
4 ${_('About')}
5 </%block>
5 </%block>
6 <%block name="header_menu">
6 <%block name="header_menu">
7 ${self.menu('about')}
7 ${self.menu('about')}
8 </%block>
8 </%block>
9 <%def name="main()">
9 <%def name="main()">
10
10
11 <div class="panel panel-primary">
11 <div class="panel panel-primary">
12 <div class="panel-heading">
12 <div class="panel-heading">
13 <h5 class="panel-title">${_('About')} Kallithea</h5>
13 <h5 class="panel-title">${_('About')} Kallithea</h5>
14 </div>
14 </div>
15
15
16 <div class="panel-body panel-about">
16 <div class="panel-body panel-about">
17 <p><a href="https://kallithea-scm.org/">Kallithea</a> is a project of the
17 <p><a href="https://kallithea-scm.org/">Kallithea</a> is a project of the
18 <a href="http://sfconservancy.org/">Software Freedom Conservancy, Inc.</a>
18 <a href="http://sfconservancy.org/">Software Freedom Conservancy, Inc.</a>
19 and is released under the terms of the
19 and is released under the terms of the
20 <a href="http://www.gnu.org/copyleft/gpl.html">GNU General Public License,
20 <a href="http://www.gnu.org/copyleft/gpl.html">GNU General Public License,
21 v 3.0 (GPLv3)</a>.</p>
21 v 3.0 (GPLv3)</a>.</p>
22
22
23 <p>Kallithea is copyrighted by various authors, including but not
23 <p>Kallithea is copyrighted by various authors, including but not
24 necessarily limited to the following:</p>
24 necessarily limited to the following:</p>
25 <ul>
25 <ul>
26
26
27 <li>Copyright &copy; 2012&ndash;2018, Mads Kiilerich</li>
27 <li>Copyright &copy; 2012&ndash;2019, Mads Kiilerich</li>
28 <li>Copyright &copy; 2012, 2014&ndash;2017, 2019, Andrej Shadura</li>
29 <li>Copyright &copy; 2014&ndash;2019, Thomas De Schampheleire</li>
30 <li>Copyright &copy; 2019, Edmund Wong</li>
31 <li>Copyright &copy; 2019, Hosted Weblate</li>
32 <li>Copyright &copy; 2019, Manuel Jacob</li>
28 <li>Copyright &copy; 2012, 2014&ndash;2018, Dominik Ruf</li>
33 <li>Copyright &copy; 2012, 2014&ndash;2018, Dominik Ruf</li>
29 <li>Copyright &copy; 2014&ndash;2018, Thomas De Schampheleire</li>
34 <li>Copyright &copy; 2014&ndash;2015, 2018, Michal ČihaΕ™</li>
30 <li>Copyright &copy; 2015, 2018, Branko Majic</li>
35 <li>Copyright &copy; 2015, 2018, Branko Majic</li>
36 <li>Copyright &copy; 2017&ndash;2018, Allan NordhΓΈy</li>
31 <li>Copyright &copy; 2018, Chris Rule</li>
37 <li>Copyright &copy; 2018, Chris Rule</li>
38 <li>Copyright &copy; 2018, JesΓΊs SΓ‘nchez</li>
32 <li>Copyright &copy; 2018, Patrick Vane</li>
39 <li>Copyright &copy; 2018, Patrick Vane</li>
40 <li>Copyright &copy; 2018, Pheng Heong Tan</li>
41 <li>Copyright &copy; 2018, ssantos</li>
42 <li>Copyright &copy; 2018, Максим Π―ΠΊΠΈΠΌΡ‡ΡƒΠΊ</li>
43 <li>Copyright &copy; 2018, ΠœΠ°Ρ€Ρ Π―ΠΌΠ±Π°Ρ€</li>
33 <li>Copyright &copy; 2012&ndash;2017, Unity Technologies</li>
44 <li>Copyright &copy; 2012&ndash;2017, Unity Technologies</li>
34 <li>Copyright &copy; 2012, 2014&ndash;2017, Andrej Shadura</li>
35 <li>Copyright &copy; 2015&ndash;2017, Γ‰tienne Gilli</li>
45 <li>Copyright &copy; 2015&ndash;2017, Γ‰tienne Gilli</li>
36 <li>Copyright &copy; 2015&ndash;2017, SΓΈren LΓΈvborg</li>
46 <li>Copyright &copy; 2015&ndash;2017, SΓΈren LΓΈvborg</li>
37 <li>Copyright &copy; 2015, 2017, Sam Jaques</li>
47 <li>Copyright &copy; 2015, 2017, Sam Jaques</li>
38 <li>Copyright &copy; 2016&ndash;2017, Asterios Dimitriou</li>
48 <li>Copyright &copy; 2016&ndash;2017, Asterios Dimitriou</li>
39 <li>Copyright &copy; 2017, Alessandro Molina</li>
49 <li>Copyright &copy; 2017, Alessandro Molina</li>
40 <li>Copyright &copy; 2017, Anton Schur</li>
50 <li>Copyright &copy; 2017, Anton Schur</li>
41 <li>Copyright &copy; 2017, Ching-Chen Mao</li>
51 <li>Copyright &copy; 2017, Ching-Chen Mao</li>
42 <li>Copyright &copy; 2017, Eivind Tagseth</li>
52 <li>Copyright &copy; 2017, Eivind Tagseth</li>
43 <li>Copyright &copy; 2017, FUJIWARA Katsunori</li>
53 <li>Copyright &copy; 2017, FUJIWARA Katsunori</li>
44 <li>Copyright &copy; 2017, Holger Schramm</li>
54 <li>Copyright &copy; 2017, Holger Schramm</li>
45 <li>Copyright &copy; 2017, Karl Goetz</li>
55 <li>Copyright &copy; 2017, Karl Goetz</li>
46 <li>Copyright &copy; 2017, Lars Kruse</li>
56 <li>Copyright &copy; 2017, Lars Kruse</li>
47 <li>Copyright &copy; 2017, Marko Semet</li>
57 <li>Copyright &copy; 2017, Marko Semet</li>
48 <li>Copyright &copy; 2017, Viktar Vauchkevich</li>
58 <li>Copyright &copy; 2017, Viktar Vauchkevich</li>
49 <li>Copyright &copy; 2012&ndash;2016, Takumi IINO</li>
59 <li>Copyright &copy; 2012&ndash;2016, Takumi IINO</li>
50 <li>Copyright &copy; 2015&ndash;2016, Jan Heylen</li>
60 <li>Copyright &copy; 2015&ndash;2016, Jan Heylen</li>
51 <li>Copyright &copy; 2015&ndash;2016, Robert Martinez</li>
61 <li>Copyright &copy; 2015&ndash;2016, Robert Martinez</li>
52 <li>Copyright &copy; 2015&ndash;2016, Robert Rauch</li>
62 <li>Copyright &copy; 2015&ndash;2016, Robert Rauch</li>
53 <li>Copyright &copy; 2016, Angel Ezquerra</li>
63 <li>Copyright &copy; 2016, Angel Ezquerra</li>
54 <li>Copyright &copy; 2016, Anton Shestakov</li>
64 <li>Copyright &copy; 2016, Anton Shestakov</li>
55 <li>Copyright &copy; 2016, Brandon Jones</li>
65 <li>Copyright &copy; 2016, Brandon Jones</li>
56 <li>Copyright &copy; 2016, Kateryna Musina</li>
66 <li>Copyright &copy; 2016, Kateryna Musina</li>
57 <li>Copyright &copy; 2016, Konstantin Veretennicov</li>
67 <li>Copyright &copy; 2016, Konstantin Veretennicov</li>
58 <li>Copyright &copy; 2016, Oscar Curero</li>
68 <li>Copyright &copy; 2016, Oscar Curero</li>
59 <li>Copyright &copy; 2016, Robert James Dennington</li>
69 <li>Copyright &copy; 2016, Robert James Dennington</li>
60 <li>Copyright &copy; 2016, timeless@gmail.com</li>
70 <li>Copyright &copy; 2016, timeless@gmail.com</li>
61 <li>Copyright &copy; 2016, YFdyh000</li>
71 <li>Copyright &copy; 2016, YFdyh000</li>
62 <li>Copyright &copy; 2012&ndash;2013, 2015, Aras Pranckevičius</li>
72 <li>Copyright &copy; 2012&ndash;2013, 2015, Aras Pranckevičius</li>
63 <li>Copyright &copy; 2014&ndash;2015, Christian Oyarzun</li>
73 <li>Copyright &copy; 2014&ndash;2015, Christian Oyarzun</li>
64 <li>Copyright &copy; 2014&ndash;2015, Joseph Rivera</li>
74 <li>Copyright &copy; 2014&ndash;2015, Joseph Rivera</li>
65 <li>Copyright &copy; 2014&ndash;2015, Michal ČihaΕ™</li>
66 <li>Copyright &copy; 2014&ndash;2015, Sean Farley</li>
75 <li>Copyright &copy; 2014&ndash;2015, Sean Farley</li>
67 <li>Copyright &copy; 2015, Anatoly Bubenkov</li>
76 <li>Copyright &copy; 2015, Anatoly Bubenkov</li>
68 <li>Copyright &copy; 2015, Andrew Bartlett</li>
77 <li>Copyright &copy; 2015, Andrew Bartlett</li>
69 <li>Copyright &copy; 2015, BalÑzs Úr</li>
78 <li>Copyright &copy; 2015, BalÑzs Úr</li>
70 <li>Copyright &copy; 2015, Ben Finney</li>
79 <li>Copyright &copy; 2015, Ben Finney</li>
71 <li>Copyright &copy; 2015, Daniel Hobley</li>
80 <li>Copyright &copy; 2015, Daniel Hobley</li>
72 <li>Copyright &copy; 2015, David Avigni</li>
81 <li>Copyright &copy; 2015, David Avigni</li>
73 <li>Copyright &copy; 2015, Denis Blanchette</li>
82 <li>Copyright &copy; 2015, Denis Blanchette</li>
74 <li>Copyright &copy; 2015, duanhongyi</li>
83 <li>Copyright &copy; 2015, duanhongyi</li>
75 <li>Copyright &copy; 2015, EriCSN Chang</li>
84 <li>Copyright &copy; 2015, EriCSN Chang</li>
76 <li>Copyright &copy; 2015, Grzegorz Krason</li>
85 <li>Copyright &copy; 2015, Grzegorz Krason</li>
77 <li>Copyright &copy; 2015, JiΕ™Γ­ Suchan</li>
86 <li>Copyright &copy; 2015, JiΕ™Γ­ Suchan</li>
78 <li>Copyright &copy; 2015, Kazunari Kobayashi</li>
87 <li>Copyright &copy; 2015, Kazunari Kobayashi</li>
79 <li>Copyright &copy; 2015, Kevin Bullock</li>
88 <li>Copyright &copy; 2015, Kevin Bullock</li>
80 <li>Copyright &copy; 2015, kobanari</li>
89 <li>Copyright &copy; 2015, kobanari</li>
81 <li>Copyright &copy; 2015, Marc Abramowitz</li>
90 <li>Copyright &copy; 2015, Marc Abramowitz</li>
82 <li>Copyright &copy; 2015, Marc Villetard</li>
91 <li>Copyright &copy; 2015, Marc Villetard</li>
83 <li>Copyright &copy; 2015, Matthias Zilk</li>
92 <li>Copyright &copy; 2015, Matthias Zilk</li>
84 <li>Copyright &copy; 2015, Michael Pohl</li>
93 <li>Copyright &copy; 2015, Michael Pohl</li>
85 <li>Copyright &copy; 2015, Michael V. DePalatis</li>
94 <li>Copyright &copy; 2015, Michael V. DePalatis</li>
86 <li>Copyright &copy; 2015, Morten Skaaning</li>
95 <li>Copyright &copy; 2015, Morten Skaaning</li>
87 <li>Copyright &copy; 2015, Nick High</li>
96 <li>Copyright &copy; 2015, Nick High</li>
88 <li>Copyright &copy; 2015, Niemand Jedermann</li>
97 <li>Copyright &copy; 2015, Niemand Jedermann</li>
89 <li>Copyright &copy; 2015, Peter Vitt</li>
98 <li>Copyright &copy; 2015, Peter Vitt</li>
90 <li>Copyright &copy; 2015, Ronny Pfannschmidt</li>
99 <li>Copyright &copy; 2015, Ronny Pfannschmidt</li>
91 <li>Copyright &copy; 2015, Tuux</li>
100 <li>Copyright &copy; 2015, Tuux</li>
92 <li>Copyright &copy; 2015, Viktar Palstsiuk</li>
101 <li>Copyright &copy; 2015, Viktar Palstsiuk</li>
93 <li>Copyright &copy; 2014, Ante Ilic</li>
102 <li>Copyright &copy; 2014, Ante Ilic</li>
94 <li>Copyright &copy; 2014, Bradley M. Kuhn</li>
103 <li>Copyright &copy; 2014, Bradley M. Kuhn</li>
95 <li>Copyright &copy; 2014, Calinou</li>
104 <li>Copyright &copy; 2014, Calinou</li>
96 <li>Copyright &copy; 2014, Daniel Anderson</li>
105 <li>Copyright &copy; 2014, Daniel Anderson</li>
97 <li>Copyright &copy; 2014, Henrik Stuart</li>
106 <li>Copyright &copy; 2014, Henrik Stuart</li>
98 <li>Copyright &copy; 2014, Ingo von Borstel</li>
107 <li>Copyright &copy; 2014, Ingo von Borstel</li>
99 <li>Copyright &copy; 2014, Jelmer VernooΔ³</li>
108 <li>Copyright &copy; 2014, Jelmer VernooΔ³</li>
100 <li>Copyright &copy; 2014, Jim Hague</li>
109 <li>Copyright &copy; 2014, Jim Hague</li>
101 <li>Copyright &copy; 2014, Matt Fellows</li>
110 <li>Copyright &copy; 2014, Matt Fellows</li>
102 <li>Copyright &copy; 2014, Max Roman</li>
111 <li>Copyright &copy; 2014, Max Roman</li>
103 <li>Copyright &copy; 2014, Na'Tosha Bard</li>
112 <li>Copyright &copy; 2014, Na'Tosha Bard</li>
104 <li>Copyright &copy; 2014, Rasmus Selsmark</li>
113 <li>Copyright &copy; 2014, Rasmus Selsmark</li>
105 <li>Copyright &copy; 2014, Tim Freund</li>
114 <li>Copyright &copy; 2014, Tim Freund</li>
106 <li>Copyright &copy; 2014, Travis Burtrum</li>
115 <li>Copyright &copy; 2014, Travis Burtrum</li>
107 <li>Copyright &copy; 2014, Zoltan Gyarmati</li>
116 <li>Copyright &copy; 2014, Zoltan Gyarmati</li>
108 <li>Copyright &copy; 2010&ndash;2013, Marcin KuΕΊmiΕ„ski</li>
117 <li>Copyright &copy; 2010&ndash;2013, Marcin KuΕΊmiΕ„ski</li>
109 <li>Copyright &copy; 2010&ndash;2013, RhodeCode GmbH</li>
118 <li>Copyright &copy; 2010&ndash;2013, RhodeCode GmbH</li>
110 <li>Copyright &copy; 2011, 2013, Aparkar</li>
119 <li>Copyright &copy; 2011, 2013, Aparkar</li>
111 <li>Copyright &copy; 2012&ndash;2013, xpol</li>
120 <li>Copyright &copy; 2012&ndash;2013, xpol</li>
112 <li>Copyright &copy; 2013, Dennis Brakhane</li>
121 <li>Copyright &copy; 2013, Dennis Brakhane</li>
113 <li>Copyright &copy; 2013, Grzegorz RoΕΌniecki</li>
122 <li>Copyright &copy; 2013, Grzegorz RoΕΌniecki</li>
114 <li>Copyright &copy; 2013, Jonathan Sternberg</li>
123 <li>Copyright &copy; 2013, Jonathan Sternberg</li>
115 <li>Copyright &copy; 2013, Leonardo Carneiro</li>
124 <li>Copyright &copy; 2013, Leonardo Carneiro</li>
116 <li>Copyright &copy; 2013, Magnus Ericmats</li>
125 <li>Copyright &copy; 2013, Magnus Ericmats</li>
117 <li>Copyright &copy; 2013, Martin Vium</li>
126 <li>Copyright &copy; 2013, Martin Vium</li>
118 <li>Copyright &copy; 2013, Simon Lopez</li>
127 <li>Copyright &copy; 2013, Simon Lopez</li>
119 <li>Copyright &copy; 2011&ndash;2012, Augusto Herrmann</li>
128 <li>Copyright &copy; 2011&ndash;2012, Augusto Herrmann</li>
120 <li>Copyright &copy; 2012, Dan Sheridan</li>
129 <li>Copyright &copy; 2012, Dan Sheridan</li>
121 <li>Copyright &copy; 2012, H Waldo G</li>
130 <li>Copyright &copy; 2012, H Waldo G</li>
122 <li>Copyright &copy; 2012, hppj</li>
131 <li>Copyright &copy; 2012, hppj</li>
123 <li>Copyright &copy; 2012, Indra Talip</li>
132 <li>Copyright &copy; 2012, Indra Talip</li>
124 <li>Copyright &copy; 2012, mikespook</li>
133 <li>Copyright &copy; 2012, mikespook</li>
125 <li>Copyright &copy; 2012, nansenat16</li>
134 <li>Copyright &copy; 2012, nansenat16</li>
126 <li>Copyright &copy; 2012, Philip Jameson</li>
135 <li>Copyright &copy; 2012, Philip Jameson</li>
127 <li>Copyright &copy; 2012, Raoul Thill</li>
136 <li>Copyright &copy; 2012, Raoul Thill</li>
128 <li>Copyright &copy; 2012, Tony Bussieres</li>
137 <li>Copyright &copy; 2012, Tony Bussieres</li>
129 <li>Copyright &copy; 2012, Vincent Duvert</li>
138 <li>Copyright &copy; 2012, Vincent Duvert</li>
130 <li>Copyright &copy; 2012, Vladislav Poluhin</li>
139 <li>Copyright &copy; 2012, Vladislav Poluhin</li>
131 <li>Copyright &copy; 2012, Zachary Auclair</li>
140 <li>Copyright &copy; 2012, Zachary Auclair</li>
132 <li>Copyright &copy; 2011, Ankit Solanki</li>
141 <li>Copyright &copy; 2011, Ankit Solanki</li>
133 <li>Copyright &copy; 2011, Dmitri Kuznetsov</li>
142 <li>Copyright &copy; 2011, Dmitri Kuznetsov</li>
134 <li>Copyright &copy; 2011, Jared Bunting</li>
143 <li>Copyright &copy; 2011, Jared Bunting</li>
135 <li>Copyright &copy; 2011, Jason Harris</li>
144 <li>Copyright &copy; 2011, Jason Harris</li>
136 <li>Copyright &copy; 2011, Les Peabody</li>
145 <li>Copyright &copy; 2011, Les Peabody</li>
137 <li>Copyright &copy; 2011, Liad Shani</li>
146 <li>Copyright &copy; 2011, Liad Shani</li>
138 <li>Copyright &copy; 2011, Lorenzo M. Catucci</li>
147 <li>Copyright &copy; 2011, Lorenzo M. Catucci</li>
139 <li>Copyright &copy; 2011, Matt Zuba</li>
148 <li>Copyright &copy; 2011, Matt Zuba</li>
140 <li>Copyright &copy; 2011, Nicolas VINOT</li>
149 <li>Copyright &copy; 2011, Nicolas VINOT</li>
141 <li>Copyright &copy; 2011, Shawn K. O'Shea</li>
150 <li>Copyright &copy; 2011, Shawn K. O'Shea</li>
142 <li>Copyright &copy; 2010, Łukasz Balcerzak</li>
151 <li>Copyright &copy; 2010, Łukasz Balcerzak</li>
143
152
144 ## We did not list the following copyright holders, given that they appeared
153 ## We did not list the following copyright holders, given that they appeared
145 ## to use for-profit company affiliations in their contribution in the
154 ## to use for-profit company affiliations in their contribution in the
146 ## Mercurial log and therefore I didn't know if copyright was theirs or
155 ## Mercurial log and therefore I didn't know if copyright was theirs or
147 ## their company's.
156 ## their company's.
148 ## Copyright &copy; 2011 Thayne Harbaugh <thayne@fusionio.com>
157 ## Copyright &copy; 2011 Thayne Harbaugh <thayne@fusionio.com>
149 ## Copyright &copy; 2012 Dies Koper <diesk@fast.au.fujitsu.com>
158 ## Copyright &copy; 2012 Dies Koper <diesk@fast.au.fujitsu.com>
150 ## Copyright &copy; 2012 Erwin Kroon <e.kroon@smartmetersolutions.nl>
159 ## Copyright &copy; 2012 Erwin Kroon <e.kroon@smartmetersolutions.nl>
151 ## Copyright &copy; 2012 Vincent Caron <vcaron@bearstech.com>
160 ## Copyright &copy; 2012 Vincent Caron <vcaron@bearstech.com>
152 ##
161 ##
153 ## These contributors' contributions may not be copyrightable:
162 ## These contributors' contributions may not be copyrightable:
154 ## philip.j@hostdime.com in 2012
163 ## philip.j@hostdime.com in 2012
155 ## Stefan Engel <mail@engel-stefan.de> in 2012
164 ## Stefan Engel <mail@engel-stefan.de> in 2012
156 ## Ton Plomp <tcplomp@gmail.com> in 2013
165 ## Ton Plomp <tcplomp@gmail.com> in 2013
157 ##
166 ##
158 </ul>
167 </ul>
159
168
160 <p>The above are the copyright holders who have submitted direct
169 <p>The above are the copyright holders who have submitted direct
161 contributions to the Kallithea repository.</p>
170 contributions to the Kallithea repository.</p>
162
171
163 <p>In the <a href="https://kallithea-scm.org/repos/kallithea">Kallithea
172 <p>In the <a href="https://kallithea-scm.org/repos/kallithea">Kallithea
164 source code</a>, there is a
173 source code</a>, there is a
165 <a href="https://kallithea-scm.org/repos/kallithea/files/tip/LICENSE.md">list
174 <a href="https://kallithea-scm.org/repos/kallithea/files/tip/LICENSE.md">list
166 of third-party libraries and code that Kallithea incorporates</a>.</p>
175 of third-party libraries and code that Kallithea incorporates</a>.</p>
167
176
168 <p>The front-end contains a <a href="${h.url('/LICENSES.txt')}">list of
177 <p>The front-end contains a <a href="${h.url('/LICENSES.txt')}">list of
169 software that is used to build the front-end</a> but isn't distributed as a
178 software that is used to build the front-end</a> but isn't distributed as a
170 part of Kallithea.</p>
179 part of Kallithea.</p>
171
180
172 </div>
181 </div>
173 </div>
182 </div>
174
183
175 </%def>
184 </%def>
@@ -1,542 +1,542 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="root.html"/>
2 <%inherit file="root.html"/>
3
3
4 <!-- CONTENT -->
4 <!-- CONTENT -->
5 <div id="content" class="container-fluid">
5 <div id="content" class="container-fluid">
6 ${self.flash_msg()}
6 ${self.flash_msg()}
7 <div id="main">
7 <div id="main">
8 ${next.main()}
8 ${next.main()}
9 </div>
9 </div>
10 </div>
10 </div>
11 <!-- END CONTENT -->
11 <!-- END CONTENT -->
12
12
13 <!-- FOOTER -->
13 <!-- FOOTER -->
14 <div class="footer navbar navbar-inverse">
14 <div class="footer navbar navbar-inverse">
15 <span class="navbar-text pull-left">
15 <span class="navbar-text pull-left">
16 ${_('Server instance: %s') % c.instance_id if c.instance_id else ''}
16 ${_('Server instance: %s') % c.instance_id if c.instance_id else ''}
17 </span>
17 </span>
18 <span class="navbar-text pull-right">
18 <span class="navbar-text pull-right">
19 This site is powered by
19 This site is powered by
20 %if c.visual.show_version:
20 %if c.visual.show_version:
21 <a class="navbar-link" href="${h.url('kallithea_project_url')}" target="_blank">Kallithea</a> ${c.kallithea_version},
21 <a class="navbar-link" href="${h.url('kallithea_project_url')}" target="_blank">Kallithea</a> ${c.kallithea_version},
22 %else:
22 %else:
23 <a class="navbar-link" href="${h.url('kallithea_project_url')}" target="_blank">Kallithea</a>,
23 <a class="navbar-link" href="${h.url('kallithea_project_url')}" target="_blank">Kallithea</a>,
24 %endif
24 %endif
25 which is
25 which is
26 <a class="navbar-link" href="${h.canonical_url('about')}#copyright">&copy; 2010&ndash;2018 by various authors &amp; licensed under GPLv3</a>.
26 <a class="navbar-link" href="${h.canonical_url('about')}#copyright">&copy; 2010&ndash;2019 by various authors &amp; licensed under GPLv3</a>.
27 %if c.issues_url:
27 %if c.issues_url:
28 &ndash; <a class="navbar-link" href="${c.issues_url}" target="_blank">${_('Support')}</a>
28 &ndash; <a class="navbar-link" href="${c.issues_url}" target="_blank">${_('Support')}</a>
29 %endif
29 %endif
30 </span>
30 </span>
31 </div>
31 </div>
32
32
33 <!-- END FOOTER -->
33 <!-- END FOOTER -->
34
34
35 ### MAKO DEFS ###
35 ### MAKO DEFS ###
36
36
37 <%block name="branding_title">
37 <%block name="branding_title">
38 %if c.site_name:
38 %if c.site_name:
39 &middot; ${c.site_name}
39 &middot; ${c.site_name}
40 %endif
40 %endif
41 </%block>
41 </%block>
42
42
43 <%def name="flash_msg()">
43 <%def name="flash_msg()">
44 <%include file="/base/flash_msg.html"/>
44 <%include file="/base/flash_msg.html"/>
45 </%def>
45 </%def>
46
46
47 <%def name="breadcrumbs()">
47 <%def name="breadcrumbs()">
48 <div class="panel-title">
48 <div class="panel-title">
49 ${self.breadcrumbs_links()}
49 ${self.breadcrumbs_links()}
50 </div>
50 </div>
51 </%def>
51 </%def>
52
52
53 <%def name="admin_menu()">
53 <%def name="admin_menu()">
54 <ul class="dropdown-menu" role="menu">
54 <ul class="dropdown-menu" role="menu">
55 <li><a href="${h.url('admin_home')}"><i class="icon-book"></i>${_('Admin Journal')}</a></li>
55 <li><a href="${h.url('admin_home')}"><i class="icon-book"></i>${_('Admin Journal')}</a></li>
56 <li><a href="${h.url('repos')}"><i class="icon-database"></i>${_('Repositories')}</a></li>
56 <li><a href="${h.url('repos')}"><i class="icon-database"></i>${_('Repositories')}</a></li>
57 <li><a href="${h.url('repos_groups')}"><i class="icon-folder"></i>${_('Repository Groups')}</a></li>
57 <li><a href="${h.url('repos_groups')}"><i class="icon-folder"></i>${_('Repository Groups')}</a></li>
58 <li><a href="${h.url('users')}"><i class="icon-user"></i>${_('Users')}</a></li>
58 <li><a href="${h.url('users')}"><i class="icon-user"></i>${_('Users')}</a></li>
59 <li><a href="${h.url('users_groups')}"><i class="icon-users"></i>${_('User Groups')}</a></li>
59 <li><a href="${h.url('users_groups')}"><i class="icon-users"></i>${_('User Groups')}</a></li>
60 <li><a href="${h.url('admin_permissions')}"><i class="icon-block"></i>${_('Default Permissions')}</a></li>
60 <li><a href="${h.url('admin_permissions')}"><i class="icon-block"></i>${_('Default Permissions')}</a></li>
61 <li><a href="${h.url('auth_home')}"><i class="icon-key"></i>${_('Authentication')}</a></li>
61 <li><a href="${h.url('auth_home')}"><i class="icon-key"></i>${_('Authentication')}</a></li>
62 <li><a href="${h.url('defaults')}"><i class="icon-wrench"></i>${_('Repository Defaults')}</a></li>
62 <li><a href="${h.url('defaults')}"><i class="icon-wrench"></i>${_('Repository Defaults')}</a></li>
63 <li class="last"><a href="${h.url('admin_settings')}"><i class="icon-gear"></i>${_('Settings')}</a></li>
63 <li class="last"><a href="${h.url('admin_settings')}"><i class="icon-gear"></i>${_('Settings')}</a></li>
64 </ul>
64 </ul>
65
65
66 </%def>
66 </%def>
67
67
68
68
69 ## admin menu used for people that have some admin resources
69 ## admin menu used for people that have some admin resources
70 <%def name="admin_menu_simple(repositories=None, repository_groups=None, user_groups=None)">
70 <%def name="admin_menu_simple(repositories=None, repository_groups=None, user_groups=None)">
71 <ul class="dropdown-menu" role="menu">
71 <ul class="dropdown-menu" role="menu">
72 %if repositories:
72 %if repositories:
73 <li><a href="${h.url('repos')}"><i class="icon-database"></i>${_('Repositories')}</a></li>
73 <li><a href="${h.url('repos')}"><i class="icon-database"></i>${_('Repositories')}</a></li>
74 %endif
74 %endif
75 %if repository_groups:
75 %if repository_groups:
76 <li><a href="${h.url('repos_groups')}"><i class="icon-folder"></i>${_('Repository Groups')}</a></li>
76 <li><a href="${h.url('repos_groups')}"><i class="icon-folder"></i>${_('Repository Groups')}</a></li>
77 %endif
77 %endif
78 %if user_groups:
78 %if user_groups:
79 <li><a href="${h.url('users_groups')}"><i class="icon-users"></i>${_('User Groups')}</a></li>
79 <li><a href="${h.url('users_groups')}"><i class="icon-users"></i>${_('User Groups')}</a></li>
80 %endif
80 %endif
81 </ul>
81 </ul>
82 </%def>
82 </%def>
83
83
84 <%def name="repolabel(repo)">
84 <%def name="repolabel(repo)">
85 %if h.is_hg(repo):
85 %if h.is_hg(repo):
86 <span class="label label-repo" title="${_('Mercurial repository')}">hg</span>
86 <span class="label label-repo" title="${_('Mercurial repository')}">hg</span>
87 %endif
87 %endif
88 %if h.is_git(repo):
88 %if h.is_git(repo):
89 <span class="label label-repo" title="${_('Git repository')}">git</span>
89 <span class="label label-repo" title="${_('Git repository')}">git</span>
90 %endif
90 %endif
91 </%def>
91 </%def>
92
92
93 <%def name="repo_context_bar(current=None, rev=None)">
93 <%def name="repo_context_bar(current=None, rev=None)">
94 <% rev = None if rev == 'tip' else rev %>
94 <% rev = None if rev == 'tip' else rev %>
95 <!--- CONTEXT BAR -->
95 <!--- CONTEXT BAR -->
96 <nav id="context-bar" class="navbar navbar-inverse">
96 <nav id="context-bar" class="navbar navbar-inverse">
97 <div class="container-fluid">
97 <div class="container-fluid">
98 <div class="navbar-header">
98 <div class="navbar-header">
99 <div class="navbar-brand">
99 <div class="navbar-brand">
100 ${repolabel(c.db_repo)}
100 ${repolabel(c.db_repo)}
101
101
102 ## public/private
102 ## public/private
103 %if c.db_repo.private:
103 %if c.db_repo.private:
104 <i class="icon-lock"></i>
104 <i class="icon-lock"></i>
105 %else:
105 %else:
106 <i class="icon-globe"></i>
106 <i class="icon-globe"></i>
107 %endif
107 %endif
108 %for group in c.db_repo.groups_with_parents:
108 %for group in c.db_repo.groups_with_parents:
109 ${h.link_to(group.name, url('repos_group_home', group_name=group.group_name), class_='navbar-link')}
109 ${h.link_to(group.name, url('repos_group_home', group_name=group.group_name), class_='navbar-link')}
110 &raquo;
110 &raquo;
111 %endfor
111 %endfor
112 ${h.link_to(c.db_repo.just_name, url('summary_home', repo_name=c.db_repo.repo_name), class_='navbar-link')}
112 ${h.link_to(c.db_repo.just_name, url('summary_home', repo_name=c.db_repo.repo_name), class_='navbar-link')}
113
113
114 %if current == 'createfork':
114 %if current == 'createfork':
115 - ${_('Create Fork')}
115 - ${_('Create Fork')}
116 %endif
116 %endif
117 </div>
117 </div>
118 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#context-pages" aria-expanded="false">
118 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#context-pages" aria-expanded="false">
119 <span class="sr-only">Toggle navigation</span>
119 <span class="sr-only">Toggle navigation</span>
120 <span class="icon-bar"></span>
120 <span class="icon-bar"></span>
121 <span class="icon-bar"></span>
121 <span class="icon-bar"></span>
122 <span class="icon-bar"></span>
122 <span class="icon-bar"></span>
123 </button>
123 </button>
124 </div>
124 </div>
125 <div id="context-pages" class="navbar-collapse collapse">
125 <div id="context-pages" class="navbar-collapse collapse">
126 <ul class="nav navbar-nav navbar-right">
126 <ul class="nav navbar-nav navbar-right">
127 <li class="${'active' if current == 'summary' else ''}" data-context="summary"><a href="${h.url('summary_home', repo_name=c.repo_name)}"><i class="icon-doc-text"></i>${_('Summary')}</a></li>
127 <li class="${'active' if current == 'summary' else ''}" data-context="summary"><a href="${h.url('summary_home', repo_name=c.repo_name)}"><i class="icon-doc-text"></i>${_('Summary')}</a></li>
128 %if rev:
128 %if rev:
129 <li class="${'active' if current == 'changelog' else ''}" data-context="changelog"><a href="${h.url('changelog_file_home', repo_name=c.repo_name, revision=rev, f_path='')}"><i class="icon-clock"></i>${_('Changelog')}</a></li>
129 <li class="${'active' if current == 'changelog' else ''}" data-context="changelog"><a href="${h.url('changelog_file_home', repo_name=c.repo_name, revision=rev, f_path='')}"><i class="icon-clock"></i>${_('Changelog')}</a></li>
130 %else:
130 %else:
131 <li class="${'active' if current == 'changelog' else ''}" data-context="changelog"><a href="${h.url('changelog_home', repo_name=c.repo_name)}"><i class="icon-clock"></i>${_('Changelog')}</a></li>
131 <li class="${'active' if current == 'changelog' else ''}" data-context="changelog"><a href="${h.url('changelog_home', repo_name=c.repo_name)}"><i class="icon-clock"></i>${_('Changelog')}</a></li>
132 %endif
132 %endif
133 <li class="${'active' if current == 'files' else ''}" data-context="files"><a href="${h.url('files_home', repo_name=c.repo_name, revision=rev or 'tip')}"><i class="icon-doc-inv"></i>${_('Files')}</a></li>
133 <li class="${'active' if current == 'files' else ''}" data-context="files"><a href="${h.url('files_home', repo_name=c.repo_name, revision=rev or 'tip')}"><i class="icon-doc-inv"></i>${_('Files')}</a></li>
134 <li class="${'active' if current == 'showpullrequest' else ''}" data-context="showpullrequest">
134 <li class="${'active' if current == 'showpullrequest' else ''}" data-context="showpullrequest">
135 <a href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}" title="${_('Show Pull Requests for %s') % c.repo_name}"> <i class="icon-git-pull-request"></i>${_('Pull Requests')}
135 <a href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}" title="${_('Show Pull Requests for %s') % c.repo_name}"> <i class="icon-git-pull-request"></i>${_('Pull Requests')}
136 %if c.repository_pull_requests:
136 %if c.repository_pull_requests:
137 <span class="badge">${c.repository_pull_requests}</span>
137 <span class="badge">${c.repository_pull_requests}</span>
138 %endif
138 %endif
139 </a>
139 </a>
140 </li>
140 </li>
141 <li class="${'active' if current == 'switch-to' else ''}" data-context="switch-to">
141 <li class="${'active' if current == 'switch-to' else ''}" data-context="switch-to">
142 <input id="branch_switcher" name="branch_switcher" type="hidden">
142 <input id="branch_switcher" name="branch_switcher" type="hidden">
143 </li>
143 </li>
144 <li class="${'active' if current == 'options' else ''} dropdown" data-context="options">
144 <li class="${'active' if current == 'options' else ''} dropdown" data-context="options">
145 %if h.HasRepoPermissionLevel('admin')(c.repo_name):
145 %if h.HasRepoPermissionLevel('admin')(c.repo_name):
146 <a href="${h.url('edit_repo',repo_name=c.repo_name)}" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false" aria-haspopup="true"><i class="icon-wrench"></i>${_('Options')} <i class="caret"></i></a>
146 <a href="${h.url('edit_repo',repo_name=c.repo_name)}" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false" aria-haspopup="true"><i class="icon-wrench"></i>${_('Options')} <i class="caret"></i></a>
147 %else:
147 %else:
148 <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false" aria-haspopup="true"><i class="icon-wrench"></i>${_('Options')} <i class="caret"></i></a>
148 <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false" aria-haspopup="true"><i class="icon-wrench"></i>${_('Options')} <i class="caret"></i></a>
149 %endif
149 %endif
150 <ul class="dropdown-menu" role="menu" aria-hidden="true">
150 <ul class="dropdown-menu" role="menu" aria-hidden="true">
151 %if h.HasRepoPermissionLevel('admin')(c.repo_name):
151 %if h.HasRepoPermissionLevel('admin')(c.repo_name):
152 <li><a href="${h.url('edit_repo',repo_name=c.repo_name)}"><i class="icon-gear"></i>${_('Settings')}</a></li>
152 <li><a href="${h.url('edit_repo',repo_name=c.repo_name)}"><i class="icon-gear"></i>${_('Settings')}</a></li>
153 %endif
153 %endif
154 %if c.db_repo.fork:
154 %if c.db_repo.fork:
155 <li><a href="${h.url('compare_url',repo_name=c.db_repo.fork.repo_name,org_ref_type=c.db_repo.landing_rev[0],org_ref_name=c.db_repo.landing_rev[1], other_repo=c.repo_name,other_ref_type='branch' if request.GET.get('branch') else c.db_repo.landing_rev[0],other_ref_name=request.GET.get('branch') or c.db_repo.landing_rev[1], merge=1)}">
155 <li><a href="${h.url('compare_url',repo_name=c.db_repo.fork.repo_name,org_ref_type=c.db_repo.landing_rev[0],org_ref_name=c.db_repo.landing_rev[1], other_repo=c.repo_name,other_ref_type='branch' if request.GET.get('branch') else c.db_repo.landing_rev[0],other_ref_name=request.GET.get('branch') or c.db_repo.landing_rev[1], merge=1)}">
156 <i class="icon-git-compare"></i>${_('Compare Fork')}</a></li>
156 <i class="icon-git-compare"></i>${_('Compare Fork')}</a></li>
157 %endif
157 %endif
158 <li><a href="${h.url('compare_home',repo_name=c.repo_name)}"><i class="icon-git-compare"></i>${_('Compare')}</a></li>
158 <li><a href="${h.url('compare_home',repo_name=c.repo_name)}"><i class="icon-git-compare"></i>${_('Compare')}</a></li>
159
159
160 <li><a href="${h.url('search_repo',repo_name=c.repo_name)}"><i class="icon-search"></i>${_('Search')}</a></li>
160 <li><a href="${h.url('search_repo',repo_name=c.repo_name)}"><i class="icon-search"></i>${_('Search')}</a></li>
161
161
162 %if h.HasRepoPermissionLevel('write')(c.repo_name) and c.db_repo.enable_locking:
162 %if h.HasRepoPermissionLevel('write')(c.repo_name) and c.db_repo.enable_locking:
163 %if c.db_repo.locked[0]:
163 %if c.db_repo.locked[0]:
164 <li><a href="${h.url('toggle_locking', repo_name=c.repo_name)}"><i class="icon-lock"></i>${_('Unlock')}</a></li>
164 <li><a href="${h.url('toggle_locking', repo_name=c.repo_name)}"><i class="icon-lock"></i>${_('Unlock')}</a></li>
165 %else:
165 %else:
166 <li><a href="${h.url('toggle_locking', repo_name=c.repo_name)}"><i class="icon-lock-open-alt"></i>${_('Lock')}</a></li>
166 <li><a href="${h.url('toggle_locking', repo_name=c.repo_name)}"><i class="icon-lock-open-alt"></i>${_('Lock')}</a></li>
167 %endif
167 %endif
168 %endif
168 %endif
169 ## TODO: this check feels wrong, it would be better to have a check for permissions
169 ## TODO: this check feels wrong, it would be better to have a check for permissions
170 ## also it feels like a job for the controller
170 ## also it feels like a job for the controller
171 %if request.authuser.username != 'default':
171 %if request.authuser.username != 'default':
172 <li>
172 <li>
173 <a href="#" class="${'following' if c.repository_following else 'follow'}" onclick="toggleFollowingRepo(this, ${c.db_repo.repo_id});">
173 <a href="#" class="${'following' if c.repository_following else 'follow'}" onclick="toggleFollowingRepo(this, ${c.db_repo.repo_id});">
174 <span class="show-follow"><i class="icon-heart-empty"></i>${_('Follow')}</span>
174 <span class="show-follow"><i class="icon-heart-empty"></i>${_('Follow')}</span>
175 <span class="show-following"><i class="icon-heart"></i>${_('Unfollow')}</span>
175 <span class="show-following"><i class="icon-heart"></i>${_('Unfollow')}</span>
176 </a>
176 </a>
177 </li>
177 </li>
178 <li><a href="${h.url('repo_fork_home',repo_name=c.repo_name)}"><i class="icon-git-pull-request"></i>${_('Fork')}</a></li>
178 <li><a href="${h.url('repo_fork_home',repo_name=c.repo_name)}"><i class="icon-git-pull-request"></i>${_('Fork')}</a></li>
179 <li><a href="${h.url('pullrequest_home',repo_name=c.repo_name)}"><i class="icon-git-pull-request"></i>${_('Create Pull Request')}</a></li>
179 <li><a href="${h.url('pullrequest_home',repo_name=c.repo_name)}"><i class="icon-git-pull-request"></i>${_('Create Pull Request')}</a></li>
180 %endif
180 %endif
181 </ul>
181 </ul>
182 </li>
182 </li>
183 </ul>
183 </ul>
184 </div>
184 </div>
185 </div>
185 </div>
186 </nav>
186 </nav>
187 <script type="text/javascript">
187 <script type="text/javascript">
188 $(document).ready(function() {
188 $(document).ready(function() {
189 var bcache = {};
189 var bcache = {};
190
190
191 var branch_switcher_placeholder = '<i class="icon-exchange"></i>' + ${h.jshtml(_('Switch To'))} + ' <span class="caret"></span>';
191 var branch_switcher_placeholder = '<i class="icon-exchange"></i>' + ${h.jshtml(_('Switch To'))} + ' <span class="caret"></span>';
192 $("#branch_switcher").select2({
192 $("#branch_switcher").select2({
193 placeholder: branch_switcher_placeholder,
193 placeholder: branch_switcher_placeholder,
194 dropdownAutoWidth: true,
194 dropdownAutoWidth: true,
195 sortResults: prefixFirstSort,
195 sortResults: prefixFirstSort,
196 formatResult: function(obj) {
196 formatResult: function(obj) {
197 return obj.text.html_escape();
197 return obj.text.html_escape();
198 },
198 },
199 formatSelection: function(obj) {
199 formatSelection: function(obj) {
200 return obj.text.html_escape();
200 return obj.text.html_escape();
201 },
201 },
202 formatNoMatches: function(term) {
202 formatNoMatches: function(term) {
203 return ${h.jshtml(_('No matches found'))};
203 return ${h.jshtml(_('No matches found'))};
204 },
204 },
205 escapeMarkup: function(m) {
205 escapeMarkup: function(m) {
206 if (m == branch_switcher_placeholder)
206 if (m == branch_switcher_placeholder)
207 return branch_switcher_placeholder;
207 return branch_switcher_placeholder;
208 return Select2.util.escapeMarkup(m);
208 return Select2.util.escapeMarkup(m);
209 },
209 },
210 containerCssClass: "branch-switcher",
210 containerCssClass: "branch-switcher",
211 dropdownCssClass: "repo-switcher-dropdown",
211 dropdownCssClass: "repo-switcher-dropdown",
212 query: function(query) {
212 query: function(query) {
213 var key = 'cache';
213 var key = 'cache';
214 var cached = bcache[key];
214 var cached = bcache[key];
215 if (cached) {
215 if (cached) {
216 var data = {
216 var data = {
217 results: []
217 results: []
218 };
218 };
219 // filter results
219 // filter results
220 $.each(cached.results, function() {
220 $.each(cached.results, function() {
221 var section = this.text;
221 var section = this.text;
222 var children = [];
222 var children = [];
223 $.each(this.children, function() {
223 $.each(this.children, function() {
224 if (query.term.length === 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
224 if (query.term.length === 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
225 children.push({
225 children.push({
226 'id': this.id,
226 'id': this.id,
227 'text': this.text,
227 'text': this.text,
228 'type': this.type,
228 'type': this.type,
229 'obj': this.obj
229 'obj': this.obj
230 });
230 });
231 }
231 }
232 });
232 });
233 if (children.length !== 0) {
233 if (children.length !== 0) {
234 data.results.push({
234 data.results.push({
235 'text': section,
235 'text': section,
236 'children': children
236 'children': children
237 });
237 });
238 }
238 }
239
239
240 });
240 });
241 query.callback(data);
241 query.callback(data);
242 } else {
242 } else {
243 $.ajax({
243 $.ajax({
244 url: pyroutes.url('repo_refs_data', {
244 url: pyroutes.url('repo_refs_data', {
245 'repo_name': ${h.js(c.repo_name)}
245 'repo_name': ${h.js(c.repo_name)}
246 }),
246 }),
247 data: {},
247 data: {},
248 dataType: 'json',
248 dataType: 'json',
249 type: 'GET',
249 type: 'GET',
250 success: function(data) {
250 success: function(data) {
251 bcache[key] = data;
251 bcache[key] = data;
252 query.callback(data);
252 query.callback(data);
253 }
253 }
254 });
254 });
255 }
255 }
256 }
256 }
257 });
257 });
258
258
259 $("#branch_switcher").on('select2-selecting', function(e) {
259 $("#branch_switcher").on('select2-selecting', function(e) {
260 e.preventDefault();
260 e.preventDefault();
261 var context = $('#context-bar .active').data('context');
261 var context = $('#context-bar .active').data('context');
262 if (context == 'files') {
262 if (context == 'files') {
263 window.location = pyroutes.url('files_home', {
263 window.location = pyroutes.url('files_home', {
264 'repo_name': REPO_NAME,
264 'repo_name': REPO_NAME,
265 'revision': e.choice.id,
265 'revision': e.choice.id,
266 'f_path': '',
266 'f_path': '',
267 'at': e.choice.text
267 'at': e.choice.text
268 });
268 });
269 } else if (context == 'changelog') {
269 } else if (context == 'changelog') {
270 if (e.choice.type == 'tag' || e.choice.type == 'book') {
270 if (e.choice.type == 'tag' || e.choice.type == 'book') {
271 $("#branch_filter").append($('<'+'option/>').val(e.choice.text));
271 $("#branch_filter").append($('<'+'option/>').val(e.choice.text));
272 }
272 }
273 $("#branch_filter").val(e.choice.text).change();
273 $("#branch_filter").val(e.choice.text).change();
274 } else {
274 } else {
275 window.location = pyroutes.url('changelog_home', {
275 window.location = pyroutes.url('changelog_home', {
276 'repo_name': ${h.js(c.repo_name)},
276 'repo_name': ${h.js(c.repo_name)},
277 'branch': e.choice.text
277 'branch': e.choice.text
278 });
278 });
279 }
279 }
280 });
280 });
281 });
281 });
282 </script>
282 </script>
283 <!--- END CONTEXT BAR -->
283 <!--- END CONTEXT BAR -->
284 </%def>
284 </%def>
285
285
286 <%def name="menu(current=None)">
286 <%def name="menu(current=None)">
287 <ul id="quick" class="nav navbar-nav navbar-right">
287 <ul id="quick" class="nav navbar-nav navbar-right">
288 <!-- repo switcher -->
288 <!-- repo switcher -->
289 <li class="${'active' if current == 'repositories' else ''}">
289 <li class="${'active' if current == 'repositories' else ''}">
290 <input id="repo_switcher" name="repo_switcher" type="hidden">
290 <input id="repo_switcher" name="repo_switcher" type="hidden">
291 </li>
291 </li>
292
292
293 ##ROOT MENU
293 ##ROOT MENU
294 %if request.authuser.username != 'default':
294 %if request.authuser.username != 'default':
295 <li class="${'active' if current == 'journal' else ''}">
295 <li class="${'active' if current == 'journal' else ''}">
296 <a class="menu_link" title="${_('Show recent activity')}" href="${h.url('journal')}">
296 <a class="menu_link" title="${_('Show recent activity')}" href="${h.url('journal')}">
297 <i class="icon-book"></i>${_('Journal')}
297 <i class="icon-book"></i>${_('Journal')}
298 </a>
298 </a>
299 </li>
299 </li>
300 %else:
300 %else:
301 <li class="${'active' if current == 'journal' else ''}">
301 <li class="${'active' if current == 'journal' else ''}">
302 <a class="menu_link" title="${_('Public journal')}" href="${h.url('public_journal')}">
302 <a class="menu_link" title="${_('Public journal')}" href="${h.url('public_journal')}">
303 <i class="icon-book"></i>${_('Public journal')}
303 <i class="icon-book"></i>${_('Public journal')}
304 </a>
304 </a>
305 </li>
305 </li>
306 %endif
306 %endif
307 <li class="${'active' if current == 'gists' else ''} dropdown">
307 <li class="${'active' if current == 'gists' else ''} dropdown">
308 <a class="menu_link dropdown-toggle" data-toggle="dropdown" role="button" title="${_('Show public gists')}" href="${h.url('gists')}">
308 <a class="menu_link dropdown-toggle" data-toggle="dropdown" role="button" title="${_('Show public gists')}" href="${h.url('gists')}">
309 <i class="icon-clippy"></i>${_('Gists')} <span class="caret"></span>
309 <i class="icon-clippy"></i>${_('Gists')} <span class="caret"></span>
310 </a>
310 </a>
311 <ul class="dropdown-menu" role="menu">
311 <ul class="dropdown-menu" role="menu">
312 <li><a href="${h.url('new_gist', public=1)}"><i class="icon-paste"></i>${_('Create New Gist')}</a></li>
312 <li><a href="${h.url('new_gist', public=1)}"><i class="icon-paste"></i>${_('Create New Gist')}</a></li>
313 <li><a href="${h.url('gists')}"><i class="icon-globe"></i>${_('All Public Gists')}</a></li>
313 <li><a href="${h.url('gists')}"><i class="icon-globe"></i>${_('All Public Gists')}</a></li>
314 %if request.authuser.username != 'default':
314 %if request.authuser.username != 'default':
315 <li><a href="${h.url('gists', public=1)}"><i class="icon-user"></i>${_('My Public Gists')}</a></li>
315 <li><a href="${h.url('gists', public=1)}"><i class="icon-user"></i>${_('My Public Gists')}</a></li>
316 <li><a href="${h.url('gists', private=1)}"><i class="icon-lock"></i>${_('My Private Gists')}</a></li>
316 <li><a href="${h.url('gists', private=1)}"><i class="icon-lock"></i>${_('My Private Gists')}</a></li>
317 %endif
317 %endif
318 </ul>
318 </ul>
319 </li>
319 </li>
320 <li class="${'active' if current == 'search' else ''}">
320 <li class="${'active' if current == 'search' else ''}">
321 <a class="menu_link" title="${_('Search in repositories')}" href="${h.url('search')}">
321 <a class="menu_link" title="${_('Search in repositories')}" href="${h.url('search')}">
322 <i class="icon-search"></i>${_('Search')}
322 <i class="icon-search"></i>${_('Search')}
323 </a>
323 </a>
324 </li>
324 </li>
325 % if h.HasPermissionAny('hg.admin')('access admin main page'):
325 % if h.HasPermissionAny('hg.admin')('access admin main page'):
326 <li class="${'active' if current == 'admin' else ''} dropdown">
326 <li class="${'active' if current == 'admin' else ''} dropdown">
327 <a class="menu_link dropdown-toggle" data-toggle="dropdown" role="button" title="${_('Admin')}" href="${h.url('admin_home')}">
327 <a class="menu_link dropdown-toggle" data-toggle="dropdown" role="button" title="${_('Admin')}" href="${h.url('admin_home')}">
328 <i class="icon-gear"></i>${_('Admin')} <span class="caret"></span>
328 <i class="icon-gear"></i>${_('Admin')} <span class="caret"></span>
329 </a>
329 </a>
330 ${admin_menu()}
330 ${admin_menu()}
331 </li>
331 </li>
332 % elif request.authuser.repositories_admin or request.authuser.repository_groups_admin or request.authuser.user_groups_admin:
332 % elif request.authuser.repositories_admin or request.authuser.repository_groups_admin or request.authuser.user_groups_admin:
333 <li class="${'active' if current == 'admin' else ''} dropdown">
333 <li class="${'active' if current == 'admin' else ''} dropdown">
334 <a class="menu_link dropdown-toggle" data-toggle="dropdown" role="button" title="${_('Admin')}" href="">
334 <a class="menu_link dropdown-toggle" data-toggle="dropdown" role="button" title="${_('Admin')}" href="">
335 <i class="icon-gear"></i>${_('Admin')}
335 <i class="icon-gear"></i>${_('Admin')}
336 </a>
336 </a>
337 ${admin_menu_simple(request.authuser.repositories_admin,
337 ${admin_menu_simple(request.authuser.repositories_admin,
338 request.authuser.repository_groups_admin,
338 request.authuser.repository_groups_admin,
339 request.authuser.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
339 request.authuser.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
340 </li>
340 </li>
341 % endif
341 % endif
342
342
343 <li class="${'active' if current == 'my_pullrequests' else ''}">
343 <li class="${'active' if current == 'my_pullrequests' else ''}">
344 <a class="menu_link" title="${_('My Pull Requests')}" href="${h.url('my_pullrequests')}">
344 <a class="menu_link" title="${_('My Pull Requests')}" href="${h.url('my_pullrequests')}">
345 <i class="icon-git-pull-request"></i>${_('My Pull Requests')}
345 <i class="icon-git-pull-request"></i>${_('My Pull Requests')}
346 %if c.my_pr_count != 0:
346 %if c.my_pr_count != 0:
347 <span class="badge">${c.my_pr_count}</span>
347 <span class="badge">${c.my_pr_count}</span>
348 %endif
348 %endif
349 </a>
349 </a>
350 </li>
350 </li>
351
351
352 ## USER MENU
352 ## USER MENU
353 <li class="dropdown">
353 <li class="dropdown">
354 <a class="menu_link dropdown-toggle" data-toggle="dropdown" role="button" id="quick_login_link"
354 <a class="menu_link dropdown-toggle" data-toggle="dropdown" role="button" id="quick_login_link"
355 aria-expanded="false" aria-controls="quick_login" href="#">
355 aria-expanded="false" aria-controls="quick_login" href="#">
356 ${h.gravatar_div(request.authuser.email, size=20, div_class="icon")}
356 ${h.gravatar_div(request.authuser.email, size=20, div_class="icon")}
357 %if request.authuser.username != 'default':
357 %if request.authuser.username != 'default':
358 <span class="menu_link_user">${request.authuser.username}</span>
358 <span class="menu_link_user">${request.authuser.username}</span>
359 %else:
359 %else:
360 <span>${_('Not Logged In')}</span>
360 <span>${_('Not Logged In')}</span>
361 %endif
361 %endif
362 <i class="caret"></i>
362 <i class="caret"></i>
363 </a>
363 </a>
364
364
365 <div class="dropdown-menu user-menu" role="menu">
365 <div class="dropdown-menu user-menu" role="menu">
366 <div id="quick_login" role="form" aria-describedby="quick_login_h" aria-hidden="true" class="container-fluid">
366 <div id="quick_login" role="form" aria-describedby="quick_login_h" aria-hidden="true" class="container-fluid">
367 %if request.authuser.username == 'default' or request.authuser.user_id is None:
367 %if request.authuser.username == 'default' or request.authuser.user_id is None:
368 ${h.form(h.url('login_home', came_from=request.path_qs), class_='form clearfix')}
368 ${h.form(h.url('login_home', came_from=request.path_qs), class_='form clearfix')}
369 <h4 id="quick_login_h">${_('Login to Your Account')}</h4>
369 <h4 id="quick_login_h">${_('Login to Your Account')}</h4>
370 <label>
370 <label>
371 ${_('Username')}:
371 ${_('Username')}:
372 ${h.text('username',class_='form-control')}
372 ${h.text('username',class_='form-control')}
373 </label>
373 </label>
374 <label>
374 <label>
375 ${_('Password')}:
375 ${_('Password')}:
376 ${h.password('password',class_='form-control')}
376 ${h.password('password',class_='form-control')}
377 </label>
377 </label>
378 <div class="password_forgotten">
378 <div class="password_forgotten">
379 ${h.link_to(_('Forgot password?'),h.url('reset_password'))}
379 ${h.link_to(_('Forgot password?'),h.url('reset_password'))}
380 </div>
380 </div>
381 <div class="register">
381 <div class="register">
382 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
382 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
383 ${h.link_to(_("Don't have an account?"),h.url('register'))}
383 ${h.link_to(_("Don't have an account?"),h.url('register'))}
384 %endif
384 %endif
385 </div>
385 </div>
386 <div class="submit">
386 <div class="submit">
387 ${h.submit('sign_in',_('Log In'),class_="btn btn-default btn-xs")}
387 ${h.submit('sign_in',_('Log In'),class_="btn btn-default btn-xs")}
388 </div>
388 </div>
389 ${h.end_form()}
389 ${h.end_form()}
390 %else:
390 %else:
391 <div class="pull-left">
391 <div class="pull-left">
392 ${h.gravatar_div(request.authuser.email, size=48, div_class="big_gravatar")}
392 ${h.gravatar_div(request.authuser.email, size=48, div_class="big_gravatar")}
393 <b class="full_name">${request.authuser.full_name_or_username}</b>
393 <b class="full_name">${request.authuser.full_name_or_username}</b>
394 <div class="email">${request.authuser.email}</div>
394 <div class="email">${request.authuser.email}</div>
395 </div>
395 </div>
396 <div id="quick_login_h" class="pull-right list-group text-right">
396 <div id="quick_login_h" class="pull-right list-group text-right">
397 ${h.link_to(_('My Account'),h.url('my_account'),class_='list-group-item')}
397 ${h.link_to(_('My Account'),h.url('my_account'),class_='list-group-item')}
398 %if not request.authuser.is_external_auth:
398 %if not request.authuser.is_external_auth:
399 ## Cannot log out if using external (container) authentication.
399 ## Cannot log out if using external (container) authentication.
400 ${h.link_to(_('Log Out'), h.url('logout_home'),class_='list-group-item')}
400 ${h.link_to(_('Log Out'), h.url('logout_home'),class_='list-group-item')}
401 %endif
401 %endif
402 </div>
402 </div>
403 %endif
403 %endif
404 </div>
404 </div>
405 </div>
405 </div>
406 </li>
406 </li>
407 </ul>
407 </ul>
408
408
409 <script type="text/javascript">
409 <script type="text/javascript">
410 $(document).ready(function(){
410 $(document).ready(function(){
411 var visual_show_public_icon = ${h.js(c.visual.show_public_icon)};
411 var visual_show_public_icon = ${h.js(c.visual.show_public_icon)};
412 var cache = {}
412 var cache = {}
413 /*format the look of items in the list*/
413 /*format the look of items in the list*/
414 var format = function(state){
414 var format = function(state){
415 if (!state.id){
415 if (!state.id){
416 return state.text.html_escape(); // optgroup
416 return state.text.html_escape(); // optgroup
417 }
417 }
418 var obj_dict = state.obj;
418 var obj_dict = state.obj;
419 var tmpl = '';
419 var tmpl = '';
420
420
421 if(obj_dict && state.type == 'repo'){
421 if(obj_dict && state.type == 'repo'){
422 tmpl += '<span class="repo-icons">';
422 tmpl += '<span class="repo-icons">';
423 if(obj_dict['repo_type'] === 'hg'){
423 if(obj_dict['repo_type'] === 'hg'){
424 tmpl += '<span class="label label-repo" title="${_('Mercurial repository')}">hg</span> ';
424 tmpl += '<span class="label label-repo" title="${_('Mercurial repository')}">hg</span> ';
425 }
425 }
426 else if(obj_dict['repo_type'] === 'git'){
426 else if(obj_dict['repo_type'] === 'git'){
427 tmpl += '<span class="label label-repo" title="${_('Git repository')}">git</span> ';
427 tmpl += '<span class="label label-repo" title="${_('Git repository')}">git</span> ';
428 }
428 }
429 if(obj_dict['private']){
429 if(obj_dict['private']){
430 tmpl += '<i class="icon-lock"></i>';
430 tmpl += '<i class="icon-lock"></i>';
431 }
431 }
432 else if(visual_show_public_icon){
432 else if(visual_show_public_icon){
433 tmpl += '<i class="icon-globe"></i>';
433 tmpl += '<i class="icon-globe"></i>';
434 }
434 }
435 tmpl += '</span>';
435 tmpl += '</span>';
436 }
436 }
437 if(obj_dict && state.type == 'group'){
437 if(obj_dict && state.type == 'group'){
438 tmpl += '<i class="icon-folder"></i>';
438 tmpl += '<i class="icon-folder"></i>';
439 }
439 }
440 tmpl += state.text.html_escape();
440 tmpl += state.text.html_escape();
441 return tmpl;
441 return tmpl;
442 }
442 }
443
443
444 var repo_switcher_placeholder = '<i class="icon-database"></i>' + ${h.jshtml(_('Repositories'))} + ' <span class="caret"></span>';
444 var repo_switcher_placeholder = '<i class="icon-database"></i>' + ${h.jshtml(_('Repositories'))} + ' <span class="caret"></span>';
445 $("#repo_switcher").select2({
445 $("#repo_switcher").select2({
446 placeholder: repo_switcher_placeholder,
446 placeholder: repo_switcher_placeholder,
447 dropdownAutoWidth: true,
447 dropdownAutoWidth: true,
448 sortResults: prefixFirstSort,
448 sortResults: prefixFirstSort,
449 formatResult: format,
449 formatResult: format,
450 formatSelection: format,
450 formatSelection: format,
451 formatNoMatches: function(term){
451 formatNoMatches: function(term){
452 return ${h.jshtml(_('No matches found'))};
452 return ${h.jshtml(_('No matches found'))};
453 },
453 },
454 containerCssClass: "repo-switcher",
454 containerCssClass: "repo-switcher",
455 dropdownCssClass: "repo-switcher-dropdown",
455 dropdownCssClass: "repo-switcher-dropdown",
456 escapeMarkup: function(m){
456 escapeMarkup: function(m){
457 if (m == repo_switcher_placeholder)
457 if (m == repo_switcher_placeholder)
458 return repo_switcher_placeholder;
458 return repo_switcher_placeholder;
459 return Select2.util.escapeMarkup(m);
459 return Select2.util.escapeMarkup(m);
460 },
460 },
461 query: function(query){
461 query: function(query){
462 var key = 'cache';
462 var key = 'cache';
463 var cached = cache[key] ;
463 var cached = cache[key] ;
464 if(cached) {
464 if(cached) {
465 var data = {results: []};
465 var data = {results: []};
466 //filter results
466 //filter results
467 $.each(cached.results, function(){
467 $.each(cached.results, function(){
468 var section = this.text;
468 var section = this.text;
469 var children = [];
469 var children = [];
470 $.each(this.children, function(){
470 $.each(this.children, function(){
471 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
471 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
472 children.push({'id': this.id, 'text': this.text, 'type': this.type, 'obj': this.obj});
472 children.push({'id': this.id, 'text': this.text, 'type': this.type, 'obj': this.obj});
473 }
473 }
474 });
474 });
475 if(children.length !== 0){
475 if(children.length !== 0){
476 data.results.push({'text': section, 'children': children});
476 data.results.push({'text': section, 'children': children});
477 }
477 }
478
478
479 });
479 });
480 query.callback(data);
480 query.callback(data);
481 }else{
481 }else{
482 $.ajax({
482 $.ajax({
483 url: ${h.js(h.url('repo_switcher_data'))},
483 url: ${h.js(h.url('repo_switcher_data'))},
484 data: {},
484 data: {},
485 dataType: 'json',
485 dataType: 'json',
486 type: 'GET',
486 type: 'GET',
487 success: function(data) {
487 success: function(data) {
488 cache[key] = data;
488 cache[key] = data;
489 query.callback({results: data.results});
489 query.callback({results: data.results});
490 }
490 }
491 });
491 });
492 }
492 }
493 }
493 }
494 });
494 });
495
495
496 $("#repo_switcher").on('select2-selecting', function(e){
496 $("#repo_switcher").on('select2-selecting', function(e){
497 e.preventDefault();
497 e.preventDefault();
498 window.location = pyroutes.url('summary_home', {'repo_name': e.val});
498 window.location = pyroutes.url('summary_home', {'repo_name': e.val});
499 });
499 });
500
500
501 $(document).on('shown.bs.dropdown', function(event) {
501 $(document).on('shown.bs.dropdown', function(event) {
502 var dropdown = $(event.target);
502 var dropdown = $(event.target);
503
503
504 dropdown.attr('aria-expanded', true);
504 dropdown.attr('aria-expanded', true);
505 dropdown.find('.dropdown-menu').attr('aria-hidden', false);
505 dropdown.find('.dropdown-menu').attr('aria-hidden', false);
506 });
506 });
507
507
508 $(document).on('hidden.bs.dropdown', function(event) {
508 $(document).on('hidden.bs.dropdown', function(event) {
509 var dropdown = $(event.target);
509 var dropdown = $(event.target);
510
510
511 dropdown.attr('aria-expanded', false);
511 dropdown.attr('aria-expanded', false);
512 dropdown.find('.dropdown-menu').attr('aria-hidden', true);
512 dropdown.find('.dropdown-menu').attr('aria-hidden', true);
513 });
513 });
514 });
514 });
515 </script>
515 </script>
516 </%def>
516 </%def>
517
517
518 <%def name="parent_child_navigation()">
518 <%def name="parent_child_navigation()">
519 <div class="pull-left">
519 <div class="pull-left">
520 <div class="parent-child-link"
520 <div class="parent-child-link"
521 data-ajax-url="${h.url('changeset_parents',repo_name=c.repo_name, revision=c.changeset.raw_id)}"
521 data-ajax-url="${h.url('changeset_parents',repo_name=c.repo_name, revision=c.changeset.raw_id)}"
522 data-linktype="parent"
522 data-linktype="parent"
523 data-reponame="${c.repo_name}">
523 data-reponame="${c.repo_name}">
524 <i class="icon-left-open"></i><a href="#">${_('Parent rev.')}</a>
524 <i class="icon-left-open"></i><a href="#">${_('Parent rev.')}</a>
525 </div>
525 </div>
526 </div>
526 </div>
527
527
528 <div class="pull-right">
528 <div class="pull-right">
529 <div class="parent-child-link"
529 <div class="parent-child-link"
530 data-ajax-url="${h.url('changeset_children',repo_name=c.repo_name, revision=c.changeset.raw_id)}"
530 data-ajax-url="${h.url('changeset_children',repo_name=c.repo_name, revision=c.changeset.raw_id)}"
531 data-linktype="child"
531 data-linktype="child"
532 data-reponame="${c.repo_name}">
532 data-reponame="${c.repo_name}">
533 <a href="#">${_('Child rev.')}</a><i class="icon-right-open"></i>
533 <a href="#">${_('Child rev.')}</a><i class="icon-right-open"></i>
534 </div>
534 </div>
535 </div>
535 </div>
536
536
537 <script type="text/javascript">
537 <script type="text/javascript">
538 $(document).ready(function(){
538 $(document).ready(function(){
539 activate_parent_child_links();
539 activate_parent_child_links();
540 });
540 });
541 </script>
541 </script>
542 </%def>
542 </%def>
@@ -1,253 +1,254 b''
1 #!/usr/bin/env python2
1 #!/usr/bin/env python2
2 # -*- coding: utf-8 -*-
2 # -*- coding: utf-8 -*-
3
3
4 """
4 """
5 Kallithea script for maintaining contributor lists from version control
5 Kallithea script for maintaining contributor lists from version control
6 history.
6 history.
7
7
8 This script and the data in it is a best effort attempt at reverse engineering
8 This script and the data in it is a best effort attempt at reverse engineering
9 previous attributions and correlate that with version control history while
9 previous attributions and correlate that with version control history while
10 preserving all existing copyright statements and attribution. This script is
10 preserving all existing copyright statements and attribution. This script is
11 processing and summarizing information found elsewhere - it is not by itself
11 processing and summarizing information found elsewhere - it is not by itself
12 making any claims. Comments in the script are an attempt at reverse engineering
12 making any claims. Comments in the script are an attempt at reverse engineering
13 possible explanations - they are not showing any intent or confirming it is
13 possible explanations - they are not showing any intent or confirming it is
14 correct.
14 correct.
15
15
16 Three files are generated / modified by this script:
16 Three files are generated / modified by this script:
17
17
18 kallithea/templates/about.html claims to show copyright holders, and the GPL
18 kallithea/templates/about.html claims to show copyright holders, and the GPL
19 license requires such existing "legal notices" to be preserved. We also try to
19 license requires such existing "legal notices" to be preserved. We also try to
20 keep it updated with copyright holders, but do not claim it is a correct list.
20 keep it updated with copyright holders, but do not claim it is a correct list.
21
21
22 CONTRIBUTORS has the purpose of giving credit where credit is due and list all
22 CONTRIBUTORS has the purpose of giving credit where credit is due and list all
23 the contributor names in the source.
23 the contributor names in the source.
24
24
25 kallithea/templates/base/base.html contains the copyright years in the page
25 kallithea/templates/base/base.html contains the copyright years in the page
26 footer.
26 footer.
27
27
28 Both make a best effort of listing all copyright holders, but revision control
28 Both make a best effort of listing all copyright holders, but revision control
29 history might be a better and more definitive source.
29 history might be a better and more definitive source.
30
30
31 Contributors are sorted "fairly" by copyright year and amount of
31 Contributors are sorted "fairly" by copyright year and amount of
32 contribution.
32 contribution.
33
33
34 New contributors are listed, without considering if the contribution contains
34 New contributors are listed, without considering if the contribution contains
35 copyrightable work.
35 copyrightable work.
36
36
37 When the copyright might belong to a different legal entity than the
37 When the copyright might belong to a different legal entity than the
38 contributor, the legal entity is given credit too.
38 contributor, the legal entity is given credit too.
39 """
39 """
40
40
41
41
42 # Some committers are so wrong that it doesn't point at any contributor:
42 # Some committers are so wrong that it doesn't point at any contributor:
43 total_ignore = set()
43 total_ignore = set()
44 total_ignore.add('*** failed to import extension hggit: No module named hggit')
44 total_ignore.add('*** failed to import extension hggit: No module named hggit')
45 total_ignore.add('<>')
45 total_ignore.add('<>')
46
46
47 # Normalize some committer names where people have contributed under different
47 # Normalize some committer names where people have contributed under different
48 # names or email addresses:
48 # names or email addresses:
49 name_fixes = {}
49 name_fixes = {}
50 name_fixes['Andrew Shadura'] = "Andrej Shadura <andrew@shadura.me>"
50 name_fixes['Andrew Shadura'] = "Andrej Shadura <andrew@shadura.me>"
51 name_fixes['aparkar'] = "Aparkar <aparkar@icloud.com>"
51 name_fixes['aparkar'] = "Aparkar <aparkar@icloud.com>"
52 name_fixes['Aras Pranckevicius'] = "Aras Pranckevičius <aras@unity3d.com>"
52 name_fixes['Aras Pranckevicius'] = "Aras Pranckevičius <aras@unity3d.com>"
53 name_fixes['Augosto Hermann'] = "Augusto Herrmann <augusto.herrmann@planejamento.gov.br>"
53 name_fixes['Augosto Hermann'] = "Augusto Herrmann <augusto.herrmann@planejamento.gov.br>"
54 name_fixes['"Bradley M. Kuhn" <bkuhn@ebb.org>'] = "Bradley M. Kuhn <bkuhn@sfconservancy.org>"
54 name_fixes['"Bradley M. Kuhn" <bkuhn@ebb.org>'] = "Bradley M. Kuhn <bkuhn@sfconservancy.org>"
55 name_fixes['dmitri.kuznetsov'] = "Dmitri Kuznetsov"
55 name_fixes['dmitri.kuznetsov'] = "Dmitri Kuznetsov"
56 name_fixes['Dmitri Kuznetsov'] = "Dmitri Kuznetsov"
56 name_fixes['Dmitri Kuznetsov'] = "Dmitri Kuznetsov"
57 name_fixes['domruf'] = "Dominik Ruf <dominikruf@gmail.com>"
57 name_fixes['domruf'] = "Dominik Ruf <dominikruf@gmail.com>"
58 name_fixes['Ingo von borstel'] = "Ingo von Borstel <kallithea@planetmaker.de>"
58 name_fixes['Ingo von borstel'] = "Ingo von Borstel <kallithea@planetmaker.de>"
59 name_fixes['Jan Heylen'] = "Jan Heylen <heyleke@gmail.com>"
59 name_fixes['Jan Heylen'] = "Jan Heylen <heyleke@gmail.com>"
60 name_fixes['Jason F. Harris'] = "Jason Harris <jason@jasonfharris.com>"
60 name_fixes['Jason F. Harris'] = "Jason Harris <jason@jasonfharris.com>"
61 name_fixes['Jelmer Vernooij'] = "Jelmer VernooΔ³ <jelmer@samba.org>"
61 name_fixes['Jelmer Vernooij'] = "Jelmer VernooΔ³ <jelmer@samba.org>"
62 name_fixes['jfh <jason@jasonfharris.com>'] = "Jason Harris <jason@jasonfharris.com>"
62 name_fixes['jfh <jason@jasonfharris.com>'] = "Jason Harris <jason@jasonfharris.com>"
63 name_fixes['Leonardo Carneiro<leonardo@unity3d.com>'] = "Leonardo Carneiro <leonardo@unity3d.com>"
63 name_fixes['Leonardo Carneiro<leonardo@unity3d.com>'] = "Leonardo Carneiro <leonardo@unity3d.com>"
64 name_fixes['leonardo'] = "Leonardo Carneiro <leonardo@unity3d.com>"
64 name_fixes['leonardo'] = "Leonardo Carneiro <leonardo@unity3d.com>"
65 name_fixes['Leonardo <leo@unity3d.com>'] = "Leonardo Carneiro <leonardo@unity3d.com>"
65 name_fixes['Leonardo <leo@unity3d.com>'] = "Leonardo Carneiro <leonardo@unity3d.com>"
66 name_fixes['Les Peabody'] = "Les Peabody <lpeabody@gmail.com>"
66 name_fixes['Les Peabody'] = "Les Peabody <lpeabody@gmail.com>"
67 name_fixes['"Lorenzo M. Catucci" <lorenzo@sancho.ccd.uniroma2.it>'] = "Lorenzo M. Catucci <lorenzo@sancho.ccd.uniroma2.it>"
67 name_fixes['"Lorenzo M. Catucci" <lorenzo@sancho.ccd.uniroma2.it>'] = "Lorenzo M. Catucci <lorenzo@sancho.ccd.uniroma2.it>"
68 name_fixes['Lukasz Balcerzak'] = "Łukasz Balcerzak <lukaszbalcerzak@gmail.com>"
68 name_fixes['Lukasz Balcerzak'] = "Łukasz Balcerzak <lukaszbalcerzak@gmail.com>"
69 name_fixes['mao <mao@lins.fju.edu.tw>'] = "Ching-Chen Mao <mao@lins.fju.edu.tw>"
69 name_fixes['mao <mao@lins.fju.edu.tw>'] = "Ching-Chen Mao <mao@lins.fju.edu.tw>"
70 name_fixes['marcink'] = "Marcin KuΕΊmiΕ„ski <marcin@python-works.com>"
70 name_fixes['marcink'] = "Marcin KuΕΊmiΕ„ski <marcin@python-works.com>"
71 name_fixes['Marcin Kuzminski'] = "Marcin KuΕΊmiΕ„ski <marcin@python-works.com>"
71 name_fixes['Marcin Kuzminski'] = "Marcin KuΕΊmiΕ„ski <marcin@python-works.com>"
72 name_fixes['nansenat16@null.tw'] = "nansenat16 <nansenat16@null.tw>"
72 name_fixes['nansenat16@null.tw'] = "nansenat16 <nansenat16@null.tw>"
73 name_fixes['Peter Vitt'] = "Peter Vitt <petervitt@web.de>"
73 name_fixes['Peter Vitt'] = "Peter Vitt <petervitt@web.de>"
74 name_fixes['philip.j@hostdime.com'] = "Philip Jameson <philip.j@hostdime.com>"
74 name_fixes['philip.j@hostdime.com'] = "Philip Jameson <philip.j@hostdime.com>"
75 name_fixes['SΓΈren LΓΈvborg'] = "SΓΈren LΓΈvborg <sorenl@unity3d.com>"
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@nokia.com>"
76 name_fixes['Thomas De Schampheleire'] = "Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>"
77 name_fixes['Weblate'] = "<>"
77 name_fixes['Weblate'] = "<>"
78 name_fixes['xpol'] = "xpol <xpolife@gmail.com>"
78 name_fixes['xpol'] = "xpol <xpolife@gmail.com>"
79 name_fixes['Lars <devel@sumpfralle.de>'] = "Lars Kruse <devel@sumpfralle.de>"
79
80
80
81
81 # Some committer email address domains that indicate that another entity might
82 # Some committer email address domains that indicate that another entity might
82 # hold some copyright too:
83 # hold some copyright too:
83 domain_extra = {}
84 domain_extra = {}
84 domain_extra['unity3d.com'] = "Unity Technologies"
85 domain_extra['unity3d.com'] = "Unity Technologies"
85 domain_extra['rhodecode.com'] = "RhodeCode GmbH"
86 domain_extra['rhodecode.com'] = "RhodeCode GmbH"
86
87
87 # Repository history show some old contributions that traditionally hasn't been
88 # Repository history show some old contributions that traditionally hasn't been
88 # listed in about.html - preserve that:
89 # listed in about.html - preserve that:
89 no_about = set(total_ignore)
90 no_about = set(total_ignore)
90 # The following contributors were traditionally not listed in about.html and it
91 # The following contributors were traditionally not listed in about.html and it
91 # seems unclear if the copyright is personal or belongs to a company.
92 # seems unclear if the copyright is personal or belongs to a company.
92 no_about.add(('Thayne Harbaugh <thayne@fusionio.com>', '2011'))
93 no_about.add(('Thayne Harbaugh <thayne@fusionio.com>', '2011'))
93 no_about.add(('Dies Koper <diesk@fast.au.fujitsu.com>', '2012'))
94 no_about.add(('Dies Koper <diesk@fast.au.fujitsu.com>', '2012'))
94 no_about.add(('Erwin Kroon <e.kroon@smartmetersolutions.nl>', '2012'))
95 no_about.add(('Erwin Kroon <e.kroon@smartmetersolutions.nl>', '2012'))
95 no_about.add(('Vincent Caron <vcaron@bearstech.com>', '2012'))
96 no_about.add(('Vincent Caron <vcaron@bearstech.com>', '2012'))
96 # These contributors' contributions might be too small to be copyrightable:
97 # These contributors' contributions might be too small to be copyrightable:
97 no_about.add(('philip.j@hostdime.com', '2012'))
98 no_about.add(('philip.j@hostdime.com', '2012'))
98 no_about.add(('Stefan Engel <mail@engel-stefan.de>', '2012'))
99 no_about.add(('Stefan Engel <mail@engel-stefan.de>', '2012'))
99 no_about.add(('Ton Plomp <tcplomp@gmail.com>', '2013'))
100 no_about.add(('Ton Plomp <tcplomp@gmail.com>', '2013'))
100 # Was reworked and contributed later and shadowed by other contributions:
101 # Was reworked and contributed later and shadowed by other contributions:
101 no_about.add(('Sean Farley <sean.michael.farley@gmail.com>', '2013'))
102 no_about.add(('Sean Farley <sean.michael.farley@gmail.com>', '2013'))
102
103
103 # Preserve contributors listed in about.html but not appearing in repository
104 # Preserve contributors listed in about.html but not appearing in repository
104 # history:
105 # history:
105 other_about = [
106 other_about = [
106 ("2011", "Aparkar <aparkar@icloud.com>"),
107 ("2011", "Aparkar <aparkar@icloud.com>"),
107 ("2010", "RhodeCode GmbH"),
108 ("2010", "RhodeCode GmbH"),
108 ("2011", "RhodeCode GmbH"),
109 ("2011", "RhodeCode GmbH"),
109 ("2012", "RhodeCode GmbH"),
110 ("2012", "RhodeCode GmbH"),
110 ("2013", "RhodeCode GmbH"),
111 ("2013", "RhodeCode GmbH"),
111 ]
112 ]
112
113
113 # Preserve contributors listed in CONTRIBUTORS but not appearing in repository
114 # Preserve contributors listed in CONTRIBUTORS but not appearing in repository
114 # history:
115 # history:
115 other_contributors = [
116 other_contributors = [
116 ("", "Andrew Kesterson <andrew@aklabs.net>"),
117 ("", "Andrew Kesterson <andrew@aklabs.net>"),
117 ("", "cejones"),
118 ("", "cejones"),
118 ("", "David A. SjΓΈen <david.sjoen@westcon.no>"),
119 ("", "David A. SjΓΈen <david.sjoen@westcon.no>"),
119 ("", "James Rhodes <jrhodes@redpointsoftware.com.au>"),
120 ("", "James Rhodes <jrhodes@redpointsoftware.com.au>"),
120 ("", "Jonas Oberschweiber <jonas.oberschweiber@d-velop.de>"),
121 ("", "Jonas Oberschweiber <jonas.oberschweiber@d-velop.de>"),
121 ("", "larikale"),
122 ("", "larikale"),
122 ("", "RhodeCode GmbH"),
123 ("", "RhodeCode GmbH"),
123 ("", "Sebastian Kreutzberger <sebastian@rhodecode.com>"),
124 ("", "Sebastian Kreutzberger <sebastian@rhodecode.com>"),
124 ("", "Steve Romanow <slestak989@gmail.com>"),
125 ("", "Steve Romanow <slestak989@gmail.com>"),
125 ("", "SteveCohen"),
126 ("", "SteveCohen"),
126 ("", "Thomas <thomas@rhodecode.com>"),
127 ("", "Thomas <thomas@rhodecode.com>"),
127 ("", "Thomas Waldmann <tw-public@gmx.de>"),
128 ("", "Thomas Waldmann <tw-public@gmx.de>"),
128 ]
129 ]
129
130
130
131
131 import os
132 import os
132 import re
133 import re
133 from collections import defaultdict
134 from collections import defaultdict
134
135
135
136
136 def sortkey(x):
137 def sortkey(x):
137 """Return key for sorting contributors "fairly":
138 """Return key for sorting contributors "fairly":
138 * latest contribution
139 * latest contribution
139 * first contribution
140 * first contribution
140 * number of contribution years
141 * number of contribution years
141 * name (with some unicode normalization)
142 * name (with some unicode normalization)
142 The entries must be 2-tuples of a list of string years and the unicode name"""
143 The entries must be 2-tuples of a list of string years and the unicode name"""
143 return (x[0] and -int(x[0][-1]),
144 return (x[0] and -int(x[0][-1]),
144 x[0] and int(x[0][0]),
145 x[0] and int(x[0][0]),
145 -len(x[0]),
146 -len(x[0]),
146 x[1].decode('utf-8').lower().replace(u'\xe9', u'e').replace(u'\u0142', u'l')
147 x[1].decode('utf-8').lower().replace(u'\xe9', u'e').replace(u'\u0142', u'l')
147 )
148 )
148
149
149
150
150 def nice_years(l, dash='-', join=' '):
151 def nice_years(l, dash='-', join=' '):
151 """Convert a list of years into brief range like '1900-1901, 1921'."""
152 """Convert a list of years into brief range like '1900-1901, 1921'."""
152 if not l:
153 if not l:
153 return ''
154 return ''
154 start = end = int(l[0])
155 start = end = int(l[0])
155 ranges = []
156 ranges = []
156 for year in l[1:] + [0]:
157 for year in l[1:] + [0]:
157 year = int(year)
158 year = int(year)
158 if year == end + 1:
159 if year == end + 1:
159 end = year
160 end = year
160 continue
161 continue
161 if start == end:
162 if start == end:
162 ranges.append('%s' % start)
163 ranges.append('%s' % start)
163 else:
164 else:
164 ranges.append('%s%s%s' % (start, dash, end))
165 ranges.append('%s%s%s' % (start, dash, end))
165 start = end = year
166 start = end = year
166 assert start == 0 and end == 0, (start, end)
167 assert start == 0 and end == 0, (start, end)
167 return join.join(ranges)
168 return join.join(ranges)
168
169
169
170
170 def insert_entries(
171 def insert_entries(
171 filename,
172 filename,
172 all_entries,
173 all_entries,
173 no_entries,
174 no_entries,
174 domain_extra,
175 domain_extra,
175 split_re,
176 split_re,
176 normalize_name,
177 normalize_name,
177 format_f):
178 format_f):
178 """Update file with contributor information.
179 """Update file with contributor information.
179 all_entries: list of tuples with year and name
180 all_entries: list of tuples with year and name
180 no_entries: set of names or name and year tuples to ignore
181 no_entries: set of names or name and year tuples to ignore
181 domain_extra: map domain name to extra credit name
182 domain_extra: map domain name to extra credit name
182 split_re: regexp matching the part of file to rewrite
183 split_re: regexp matching the part of file to rewrite
183 normalize_name: function to normalize names for grouping and display
184 normalize_name: function to normalize names for grouping and display
184 format_f: function formatting year list and name to a string
185 format_f: function formatting year list and name to a string
185 """
186 """
186 name_years = defaultdict(set)
187 name_years = defaultdict(set)
187
188
188 for year, name in all_entries:
189 for year, name in all_entries:
189 if name in no_entries or (name, year) in no_entries:
190 if name in no_entries or (name, year) in no_entries:
190 continue
191 continue
191 domain = name.split('@', 1)[-1].rstrip('>')
192 domain = name.split('@', 1)[-1].rstrip('>')
192 if domain in domain_extra:
193 if domain in domain_extra:
193 name_years[domain_extra[domain]].add(year)
194 name_years[domain_extra[domain]].add(year)
194 name_years[normalize_name(name)].add(year)
195 name_years[normalize_name(name)].add(year)
195
196
196 l = [(list(sorted(year for year in years if year)), name)
197 l = [(list(sorted(year for year in years if year)), name)
197 for name, years in name_years.items()]
198 for name, years in name_years.items()]
198 l.sort(key=sortkey)
199 l.sort(key=sortkey)
199
200
200 with open(filename) as f:
201 with open(filename) as f:
201 pre, post = re.split(split_re, f.read())
202 pre, post = re.split(split_re, f.read())
202
203
203 with open(filename, 'w') as f:
204 with open(filename, 'w') as f:
204 f.write(pre +
205 f.write(pre +
205 ''.join(format_f(years, name) for years, name in l) +
206 ''.join(format_f(years, name) for years, name in l) +
206 post)
207 post)
207
208
208
209
209 def main():
210 def main():
210 repo_entries = [
211 repo_entries = [
211 (year, name_fixes.get(name) or name_fixes.get(name.rsplit('<', 1)[0].strip()) or name)
212 (year, name_fixes.get(name) or name_fixes.get(name.rsplit('<', 1)[0].strip()) or name)
212 for year, name in
213 for year, name in
213 (line.strip().split(' ', 1)
214 (line.strip().split(' ', 1)
214 for line in os.popen("""hg log -r '::.' -T '{date(date,"%Y")} {author}\n'""").readlines())
215 for line in os.popen("""hg log -r '::.' -T '{date(date,"%Y")} {author}\n'""").readlines())
215 ]
216 ]
216
217
217 insert_entries(
218 insert_entries(
218 filename='kallithea/templates/about.html',
219 filename='kallithea/templates/about.html',
219 all_entries=repo_entries + other_about,
220 all_entries=repo_entries + other_about,
220 no_entries=no_about,
221 no_entries=no_about,
221 domain_extra=domain_extra,
222 domain_extra=domain_extra,
222 split_re=r'(?: <li>Copyright &copy; [^\n]*</li>\n)*',
223 split_re=r'(?: <li>Copyright &copy; [^\n]*</li>\n)*',
223 normalize_name=lambda name: name.split('<', 1)[0].strip(),
224 normalize_name=lambda name: name.split('<', 1)[0].strip(),
224 format_f=lambda years, name: ' <li>Copyright &copy; %s, %s</li>\n' % (nice_years(years, '&ndash;', ', '), name),
225 format_f=lambda years, name: ' <li>Copyright &copy; %s, %s</li>\n' % (nice_years(years, '&ndash;', ', '), name),
225 )
226 )
226
227
227 insert_entries(
228 insert_entries(
228 filename='CONTRIBUTORS',
229 filename='CONTRIBUTORS',
229 all_entries=repo_entries + other_contributors,
230 all_entries=repo_entries + other_contributors,
230 no_entries=total_ignore,
231 no_entries=total_ignore,
231 domain_extra=domain_extra,
232 domain_extra=domain_extra,
232 split_re=r'(?: [^\n]*\n)*',
233 split_re=r'(?: [^\n]*\n)*',
233 normalize_name=lambda name: name,
234 normalize_name=lambda name: name,
234 format_f=lambda years, name: (' %s%s%s\n' % (name, ' ' if years else '', nice_years(years))),
235 format_f=lambda years, name: (' %s%s%s\n' % (name, ' ' if years else '', nice_years(years))),
235 )
236 )
236
237
237 insert_entries(
238 insert_entries(
238 filename='kallithea/templates/base/base.html',
239 filename='kallithea/templates/base/base.html',
239 all_entries=repo_entries,
240 all_entries=repo_entries,
240 no_entries=total_ignore,
241 no_entries=total_ignore,
241 domain_extra={},
242 domain_extra={},
242 split_re=r'(?<=&copy;) .* (?=by various authors)',
243 split_re=r'(?<=&copy;) .* (?=by various authors)',
243 normalize_name=lambda name: '',
244 normalize_name=lambda name: '',
244 format_f=lambda years, name: ' ' + nice_years(years, '&ndash;', ', ') + ' ',
245 format_f=lambda years, name: ' ' + nice_years(years, '&ndash;', ', ') + ' ',
245 )
246 )
246
247
247
248
248 if __name__ == '__main__':
249 if __name__ == '__main__':
249 main()
250 main()
250
251
251
252
252 # To list new contributors since last tagging:
253 # To list new contributors since last tagging:
253 # { hg log -r '::tagged()' -T ' {author}\n {author}\n'; hg log -r '::.' -T ' {author}\n' | sort | uniq; } | sort | uniq -u
254 # { 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